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.Core; 8 using Antmicro.Renode.Peripherals.CPU; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Time; 12 using System; 13 using System.Linq; 14 using System.Collections.Generic; 15 using System.Collections.ObjectModel; 16 17 namespace Antmicro.Renode.Peripherals.Timers 18 { 19 public class AmbiqApollo4_Timer : BasicDoubleWordPeripheral, INumberedGPIOOutput, IKnownSize 20 { AmbiqApollo4_Timer(IMachine machine)21 public AmbiqApollo4_Timer(IMachine machine) : base(machine) 22 { 23 var innerConnections = new Dictionary<int, IGPIO>(); 24 internalTimers = new InternalTimer[TimersCount]; 25 for(var i = 0; i < TimersCount; ++i) 26 { 27 internalTimers[i] = new InternalTimer(this, machine.ClockSource, i); 28 internalTimers[i].OnCompare += UpdateInterrupts; 29 innerConnections[i] = new GPIO(); 30 } 31 32 padOutput = new IEnumRegisterField<PadOutput>[OutputConfigRegisters * OutputConfigFieldsPerRegister]; 33 timerEnabled = new IFlagRegisterField[TimersCount]; 34 functionSelect = new IEnumRegisterField<FunctionSelect>[TimersCount]; 35 triggerMode = new IEnumRegisterField<TriggerMode>[TimersCount]; 36 triggerSource = new IEnumRegisterField<TriggerSource>[TimersCount]; 37 38 Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections); 39 40 DefineRegisters(); 41 Reset(); 42 } 43 Reset()44 public override void Reset() 45 { 46 base.Reset(); 47 for(var i = 0; i < TimersCount; ++i) 48 { 49 internalTimers[i].Reset(); 50 Connections[i].Unset(); 51 } 52 } 53 54 public IReadOnlyDictionary<int, IGPIO> Connections { get; } 55 56 public long Size => 0x800; 57 GetFrequencyAndDivider(ClockSelect clockSelect, out uint divider)58 private long GetFrequencyAndDivider(ClockSelect clockSelect, out uint divider) 59 { 60 divider = 1; 61 var frequency = 1L; 62 63 switch(clockSelect) 64 { 65 case ClockSelect.HFRCDiv16: 66 frequency = HFRCFrequency; 67 divider = 16; 68 break; 69 case ClockSelect.HFRCDiv64: 70 frequency = HFRCFrequency; 71 divider = 64; 72 break; 73 case ClockSelect.HFRCDiv256: 74 frequency = HFRCFrequency; 75 divider = 256; 76 break; 77 case ClockSelect.HFRCDiv1024: 78 frequency = HFRCFrequency; 79 divider = 1024; 80 break; 81 case ClockSelect.HFRCDiv4K: 82 frequency = HFRCFrequency; 83 divider = 4096; 84 break; 85 case ClockSelect.LFRC: 86 frequency = LFRCFrequency; 87 break; 88 case ClockSelect.LFRCDiv2: 89 frequency = LFRCFrequency; 90 divider = 2; 91 break; 92 case ClockSelect.LFRCDiv32: 93 frequency = LFRCFrequency; 94 divider = 32; 95 break; 96 case ClockSelect.LFRCDiv1K: 97 frequency = LFRCFrequency; 98 divider = 1024; 99 break; 100 case ClockSelect.XT: 101 frequency = XTFrequency; 102 break; 103 case ClockSelect.XTDiv2: 104 frequency = XTFrequency; 105 divider = 2; 106 break; 107 case ClockSelect.XTDiv4: 108 frequency = XTFrequency; 109 divider = 4; 110 break; 111 case ClockSelect.XTDiv8: 112 frequency = XTFrequency; 113 divider = 8; 114 break; 115 case ClockSelect.XTDiv16: 116 frequency = XTFrequency; 117 divider = 16; 118 break; 119 case ClockSelect.XTDiv32: 120 frequency = XTFrequency; 121 divider = 32; 122 break; 123 case ClockSelect.XTDiv128: 124 frequency = XTFrequency; 125 divider = 128; 126 break; 127 case ClockSelect.RTC_100HZ: 128 frequency = 100; 129 break; 130 default: 131 this.Log(LogLevel.Warning, "{0} is not supported; set default frequency of 1Hz", clockSelect); 132 break; 133 } 134 return frequency; 135 } 136 UpdateTimerActiveStatus()137 private void UpdateTimerActiveStatus() 138 { 139 for(var i = 0 ; i < TimersCount; ++i) 140 { 141 internalTimers[i].Enabled = timerEnabled[i].Value && globalTimerEnabled[i].Value; 142 } 143 } 144 UpdateInterrupts()145 private void UpdateInterrupts() 146 { 147 for(var i = 0; i < TimersCount; ++i) 148 { 149 var interrupt = false; 150 interrupt |= internalTimers[i].Compare0Event && internalTimers[i].Compare0Interrupt; 151 interrupt |= internalTimers[i].Compare1Event && internalTimers[i].Compare1Interrupt; 152 153 if(Connections[i].IsSet != interrupt) 154 { 155 this.NoisyLog("Changing Interrupt{0} from {1} to {2}", i, Connections[i].IsSet, interrupt); 156 } 157 158 Connections[i].Set(interrupt); 159 } 160 } 161 DefineRegisters()162 private void DefineRegisters() 163 { 164 Registers.Control.Define(this) 165 .WithReservedBits(0, 31) 166 .WithFlag(31, FieldMode.WriteOneToClear, name: "RESET", 167 writeCallback: (_, value) => { if(value) Reset(); }) 168 ; 169 170 Registers.Status.Define(this) 171 .WithValueField(0, 16, FieldMode.Read, name: "ACTIVE", 172 valueProviderCallback: _ => (uint)internalTimers.Count(timer => timer.Enabled)) 173 .WithValueField(16, 5, FieldMode.Read, name: "NTIMERS", 174 valueProviderCallback: _ => TimersCount) 175 .WithReservedBits(21, 11) 176 ; 177 178 Registers.GlobalEnable.Define(this, 0x7ff) 179 .WithFlags(0, 16, out globalTimerEnabled, name: "ENB") 180 .WithChangeCallback((_, __) => UpdateTimerActiveStatus()) 181 ; 182 183 { 184 var interruptEnable = Registers.InterruptEnable.Define(this) 185 .WithWriteCallback((_, __) => UpdateInterrupts()); 186 var interruptStatus = Registers.InterruptStatus.Define(this) 187 .WithWriteCallback((_, __) => UpdateInterrupts()); 188 var interruptClear = Registers.InterruptClear.Define(this) 189 .WithWriteCallback((_, __) => UpdateInterrupts()); 190 var interruptSet = Registers.InterruptSet.Define(this) 191 .WithWriteCallback((_, __) => UpdateInterrupts()); 192 193 for(var i = 0; i < TimersCount; ++i) 194 { 195 var index = i; 196 197 interruptEnable 198 .WithFlag(2 * index, name: $"TMR{index}0INT", 199 valueProviderCallback: _ => internalTimers[index].Compare0Interrupt, 200 writeCallback: (_, value) => internalTimers[index].Compare0Interrupt = value) 201 .WithFlag(2 * index + 1, name: $"TMR{index}1INT", 202 valueProviderCallback: _ => internalTimers[index].Compare1Interrupt, 203 writeCallback: (_, value) => internalTimers[index].Compare1Interrupt = value) 204 ; 205 206 interruptStatus 207 .WithFlag(2 * index, name: $"TMR{index}0INTSTAT", 208 valueProviderCallback: _ => internalTimers[index].Compare0Event, 209 writeCallback: (_, value) => internalTimers[index].Compare0Event = value) 210 .WithFlag(2 * index + 1, name: $"TMR{index}1INTSTAT", 211 valueProviderCallback: _ => internalTimers[index].Compare1Event, 212 writeCallback: (_, value) => internalTimers[index].Compare1Event = value) 213 ; 214 215 interruptClear 216 .WithFlag(2 * index, name: $"TMR{index}0INTCLR", 217 valueProviderCallback: _ => internalTimers[index].Compare0Event, 218 writeCallback: (_, value) => { if(value) internalTimers[index].Compare0Event = false; }) 219 .WithFlag(2 * index + 1, name: $"TMR{index}1INTCLR", 220 valueProviderCallback: _ => internalTimers[index].Compare1Event, 221 writeCallback: (_, value) => { if(value) internalTimers[index].Compare1Event = false; }) 222 ; 223 224 interruptSet 225 .WithFlag(2 * index, name: $"TMR{index}0INTSET", 226 valueProviderCallback: _ => internalTimers[index].Compare0Event, 227 writeCallback: (_, value) => { if(value) internalTimers[index].Compare0Event = true; }) 228 .WithFlag(2 * index + 1, name: $"TMR{index}1INTSET", 229 valueProviderCallback: _ => internalTimers[index].Compare1Event, 230 writeCallback: (_, value) => { if(value) internalTimers[index].Compare1Event = true; }) 231 ; 232 } 233 } 234 235 Registers.OutputConfig0.DefineMany(this, OutputConfigRegisters, (register, index) => 236 { 237 register 238 .WithEnumField(0, 6, out padOutput[index * 4], name: $"OUTCFG{index * 4}") 239 .WithReservedBits(6, 2) 240 .WithEnumField(8, 6, out padOutput[index * 4 + 1], name: $"OUTCFG{index * 4 + 1}") 241 .WithReservedBits(14, 2) 242 .WithEnumField(16, 6, out padOutput[index * 4 + 2], name: $"OUTCFG{index * 4 + 2}") 243 .WithReservedBits(22, 2) 244 .WithEnumField(24, 6, out padOutput[index * 4 + 3], name: $"OUTCFG{index * 4 + 3}") 245 .WithReservedBits(30, 2) 246 ; 247 }); 248 249 Registers.Timer0Control.DefineMany(this, TimersCount, (register, index) => 250 { 251 register 252 .WithFlag(0, out timerEnabled[index], name: $"TMR{index}EN", 253 writeCallback: (_, value) => 254 { 255 UpdateTimerActiveStatus(); 256 }) 257 .WithFlag(1, FieldMode.WriteOneToClear, name: $"TMR{index}CLR", 258 writeCallback: (_, value) => { if(value) internalTimers[index].Reset(); }) 259 .WithTaggedFlag($"TMR{index}POL0", 2) 260 .WithTaggedFlag($"TMR{index}POL1", 3) 261 .WithEnumField(4, 4, out functionSelect[index], name: $"TMR{index}FN", 262 writeCallback: (_, value) => 263 { 264 switch(value) 265 { 266 case FunctionSelect.Continous: 267 internalTimers[index].OneShot = false; 268 break; 269 case FunctionSelect.Upcount: 270 internalTimers[index].OneShot = true; 271 break; 272 default: 273 this.Log(LogLevel.Error, "Timer{0}: {1} function mode is not supported", index, value); 274 break; 275 } 276 }) 277 .WithEnumField<DoubleWordRegister, ClockSelect>(8, 8, name: $"TMR{index}CLK", 278 changeCallback: (_, newValue) => 279 { 280 var frequency = GetFrequencyAndDivider(newValue, out var divider); 281 internalTimers[index].Frequency = frequency; 282 internalTimers[index].Divider = divider; 283 }) 284 .WithEnumField(16, 2, out triggerMode[index], name: $"TMR{index}TMODE") 285 .WithReservedBits(18, 6) 286 .WithTag($"TMR{index}LMT", 24, 8) 287 ; 288 }, stepInBytes: TimerStructureSize); 289 290 Registers.Timer0.DefineMany(this, TimersCount, (register, index) => 291 { 292 register 293 .WithValueField(0, 32, name: $"TIMER{index}", 294 valueProviderCallback: _ => 295 { 296 if(machine.SystemBus.TryGetCurrentCPU(out var cpu)) 297 { 298 cpu.SyncTime(); 299 } 300 return (uint)internalTimers[index].Value; 301 }, 302 writeCallback: (_, value) => internalTimers[index].Value = (ulong)value) 303 ; 304 }, stepInBytes: TimerStructureSize); 305 306 Registers.Timer0Compare0.DefineMany(this, TimersCount, (register, index) => 307 { 308 register 309 .WithValueField(0, 32, name: $"TMR{index}CMP0", 310 valueProviderCallback: _ => (uint)internalTimers[index].Compare0, 311 writeCallback: (_, value) => internalTimers[index].Compare0 = (ulong)value) 312 ; 313 }, stepInBytes: TimerStructureSize); 314 315 Registers.Timer0Compare1.DefineMany(this, TimersCount, (register, index) => 316 { 317 register 318 .WithValueField(0, 32, name: $"TMR{index}CMP1", 319 valueProviderCallback: _ => (uint)internalTimers[index].Compare1, 320 writeCallback: (_, value) => internalTimers[index].Compare1 = (ulong)value) 321 ; 322 }, stepInBytes: TimerStructureSize); 323 324 Registers.Timer0Mode.DefineMany(this, TimersCount, (register, index) => 325 { 326 register 327 .WithReservedBits(0, 8) 328 .WithEnumField(8, 8, out triggerSource[index], name: $"TMR{index}TRIGSEL") 329 .WithReservedBits(16, 16) 330 ; 331 }, stepInBytes: TimerStructureSize); 332 } 333 334 private readonly InternalTimer[] internalTimers; 335 336 private IFlagRegisterField[] timerEnabled; 337 private IFlagRegisterField[] globalTimerEnabled; 338 339 private IEnumRegisterField<PadOutput>[] padOutput; 340 341 private IEnumRegisterField<FunctionSelect>[] functionSelect; 342 private IEnumRegisterField<TriggerMode>[] triggerMode; 343 private IEnumRegisterField<TriggerSource>[] triggerSource; 344 345 private const int TimerStructureSize = 0x20; 346 private const int TimersCount = 16; 347 private const long HFRCFrequency = 96000000; 348 private const long LFRCFrequency = 1000; 349 private const long XTFrequency = 32768; 350 private const int OutputConfigRegisters = 32; 351 private const int OutputConfigFieldsPerRegister = 4; 352 353 private class InternalTimer 354 { InternalTimer(IPeripheral parent, IClockSource clockSource, int index)355 public InternalTimer(IPeripheral parent, IClockSource clockSource, int index) 356 { 357 compare0Timer = new ComparingTimer(clockSource, 1, parent, $"timer{index}cmp0", limit: 0xFFFFFFFF, compare: 0xFFFFFFFF, enabled: false); 358 compare1Timer = new ComparingTimer(clockSource, 1, parent, $"timer{index}cmp1", limit: 0xFFFFFFFF, compare: 0xFFFFFFFF, enabled: false); 359 360 compare0Timer.CompareReached += () => 361 { 362 Compare0Event = true; 363 CompareReached(); 364 }; 365 compare1Timer.CompareReached += () => 366 { 367 Compare1Event = true; 368 CompareReached(); 369 }; 370 } 371 Reset()372 public void Reset() 373 { 374 Enabled = false; 375 Compare0Event = false; 376 Compare1Event = false; 377 } 378 379 public bool Enabled 380 { 381 get => compare0Timer.Enabled; 382 set 383 { 384 if(Enabled == value) 385 { 386 return; 387 } 388 389 Value = 0; 390 compare0Timer.Enabled = value; 391 compare1Timer.Enabled = value; 392 } 393 } 394 395 public bool OneShot { get; set; } 396 397 public ulong Value 398 { 399 get => compare0Timer.Value; 400 set 401 { 402 compare0Timer.Value = value; 403 compare1Timer.Value = value; 404 } 405 } 406 407 public long Frequency 408 { 409 get => compare0Timer.Frequency; 410 set 411 { 412 compare0Timer.Frequency = value; 413 compare1Timer.Frequency = value; 414 } 415 } 416 417 public uint Divider 418 { 419 get => compare0Timer.Divider; 420 set 421 { 422 compare0Timer.Divider = value; 423 compare1Timer.Divider = value; 424 } 425 } 426 427 public ulong Compare0 428 { 429 get => compare0Timer.Compare; 430 set => compare0Timer.Compare = value; 431 } 432 433 public ulong Compare1 434 { 435 get => compare1Timer.Compare; 436 set => compare1Timer.Compare = value; 437 } 438 439 public bool Compare0Event { get; set; } 440 public bool Compare1Event { get; set; } 441 442 public bool Compare0Interrupt 443 { 444 get => compare0Timer.EventEnabled; 445 set => compare0Timer.EventEnabled = value; 446 } 447 448 public bool Compare1Interrupt 449 { 450 get => compare1Timer.EventEnabled; 451 set => compare1Timer.EventEnabled = value; 452 } 453 454 public Action OnCompare; 455 CompareReached()456 private void CompareReached() 457 { 458 OnCompare?.Invoke(); 459 460 if(OneShot) 461 { 462 Value = 0; 463 } 464 } 465 466 private readonly ComparingTimer compare0Timer; 467 private readonly ComparingTimer compare1Timer; 468 } 469 470 private enum TriggerSource 471 { 472 Timer0Output0 = 0x00, // Trigger source is TIMER 0 Output 0 473 Timer0Output1 = 0x01, // Trigger source is TIMER 0 Output 1 474 Timer1Output0 = 0x02, // Trigger source is TIMER 1 Output 0 475 Timer1Output1 = 0x03, // Trigger source is TIMER 1 Output 1 476 Timer2Output0 = 0x04, // Trigger source is TIMER 2 Output 0 477 Timer2Output1 = 0x05, // Trigger source is TIMER 2 Output 1 478 Timer3Output0 = 0x06, // Trigger source is TIMER 3 Output 0 479 Timer3Output1 = 0x07, // Trigger source is TIMER 3 Output 1 480 Timer4Output0 = 0x08, // Trigger source is TIMER 4 Output 0 481 Timer4Output1 = 0x09, // Trigger source is TIMER 4 Output 1 482 Timer5Output0 = 0x0A, // Trigger source is TIMER 5 Output 0 483 Timer5Output1 = 0x0B, // Trigger source is TIMER 5 Output 1 484 Timer6Output0 = 0x0C, // Trigger source is TIMER 6 Output 0 485 Timer6Output1 = 0x0D, // Trigger source is TIMER 6 Output 1 486 Timer7Output0 = 0x0E, // Trigger source is TIMER 7 Output 0 487 Timer7Output1 = 0x0F, // Trigger source is TIMER 7 Output 1 488 Timer8Output0 = 0x10, // Trigger source is TIMER 8 Output 0 489 Timer8Output1 = 0x11, // Trigger source is TIMER 8 Output 1 490 Timer9Output0 = 0x12, // Trigger source is TIMER 9 Output 0 491 Timer9Output1 = 0x13, // Trigger source is TIMER 9 Output 1 492 Timer10Output0 = 0x14, // Trigger source is TIMER 10 Output 0 493 Timer10Output1 = 0x15, // Trigger source is TIMER 10 Output 1 494 Timer11Output0 = 0x16, // Trigger source is TIMER 11 Output 0 495 Timer11Output1 = 0x17, // Trigger source is TIMER 11 Output 1 496 Timer12Output0 = 0x18, // Trigger source is TIMER 12 Output 0 497 Timer12Output1 = 0x19, // Trigger source is TIMER 12 Output 1 498 Timer13Output0 = 0x1A, // Trigger source is TIMER 13 Output 0 499 Timer13Output1 = 0x1B, // Trigger source is TIMER 13 Output 1 500 Timer14Output0 = 0x1C, // Trigger source is TIMER 14 Output 0 501 Timer14Output1 = 0x1D, // Trigger source is TIMER 14 Output 1 502 Timer15Output0 = 0x1E, // Trigger source is TIMER 15 Output 0 503 Timer15Output1 = 0x1F, // Trigger source is TIMER 15 Output 1 504 STimerCompare0 = 0x30, // Trigger source is STIMER Compare 0 505 STimerCompare1 = 0x31, // Trigger source is STIMER Compare 1 506 STimerCompare2 = 0x32, // Trigger source is STIMER Compare 2 507 STimerCompare3 = 0x33, // Trigger source is STIMER Compare 3 508 STimerCompare4 = 0x34, // Trigger source is STIMER Compare 4 509 STimerCompare5 = 0x35, // Trigger source is STIMER Compare 5 510 STimerCompare6 = 0x36, // Trigger source is STIMER Compare 6 511 STimerCompare7 = 0x37, // Trigger source is STIMER Compare 7 512 STimerCapture0 = 0x38, // Trigger source is STIMER Capture 0 513 STimerCapture1 = 0x39, // Trigger source is STIMER Capture 1 514 STimerCapture2 = 0x3A, // Trigger source is STIMER Capture 2 515 STimerCapture3 = 0x3B, // Trigger source is STIMER Capture 3 516 STimerCapture4 = 0x3C, // Trigger source is STIMER Capture 4 517 STimerCapture5 = 0x3D, // Trigger source is STIMER Capture 5 518 STimerCapture6 = 0x3E, // Trigger source is STIMER Capture 6 519 STimerCapture7 = 0x3F, // Trigger source is STIMER Capture 7 520 GPIO0 = 0x80, // Trigger source is GPIO #0 521 GPIO127 = 0xFF, // Trigger source is GPIO #127 522 } 523 524 private enum TriggerMode 525 { 526 Disable = 0x00, 527 RisingEdge = 0x01, 528 FallingEdge = 0x02, 529 EitherEdge = 0x03, 530 } 531 532 private enum ClockSelect 533 { 534 HFRCDiv16 = 0x01, // Clock source is HFRC / 16 535 HFRCDiv64 = 0x02, // Clock source is HFRC / 64 536 HFRCDiv256 = 0x03, // Clock source is HFRC / 256 537 HFRCDiv1024 = 0x04, // Clock source is HFRC / 1024 538 HFRCDiv4K = 0x05, // Clock source is HFRC / 4096 539 LFRC = 0x06, // Clock source is LFRC 540 LFRCDiv2 = 0x07, // Clock source is LFRC / 2 541 LFRCDiv32 = 0x08, // Clock source is LFRC / 32 542 LFRCDiv1K = 0x09, // Clock source is LFRC / 1024 543 XT = 0x0A, // Clock source is the XT (uncalibrated). 544 XTDiv2 = 0x0B, // Clock source is XT / 2 545 XTDiv4 = 0x0C, // Clock source is XT / 4 546 XTDiv8 = 0x0D, // Clock source is XT / 8 547 XTDiv16 = 0x0E, // Clock source is XT / 16 548 XTDiv32 = 0x0F, // Clock source is XT / 32 549 XTDiv128 = 0x10, // Clock source is XT / 128 550 RTC_100HZ = 0x11, // Clock source is 100 Hz from the current RTC oscillator. 551 BuckC = 0x1C, // Clock source is Buck VDDC TON pulses. 552 BuckF = 0x1D, // Clock source is Buck VDDF TON pulses. 553 BuckS = 0x1E, // Clock source is Buck VDDS TON pulses. 554 BuckCLV = 0x1F, // Clock source is Buck VDDC_LV TON pulses. 555 Timer0Output0 = 0x20, // Clock source is TIMER 0 Output 0 556 Timer0Output1 = 0x21, // Clock source is TIMER 0 Output 1 557 Timer1Output0 = 0x22, // Clock source is TIMER 1 Output 0 558 Timer1Output1 = 0x23, // Clock source is TIMER 1 Output 1 559 Timer2Output0 = 0x24, // Clock source is TIMER 2 Output 0 560 Timer2Output1 = 0x25, // Clock source is TIMER 2 Output 1 561 Timer3Output0 = 0x26, // Clock source is TIMER 3 Output 0 562 Timer3Output1 = 0x27, // Clock source is TIMER 3 Output 1 563 Timer4Output0 = 0x28, // Clock source is TIMER 4 Output 0 564 Timer4Output1 = 0x29, // Clock source is TIMER 4 Output 1 565 Timer5Output0 = 0x2A, // Clock source is TIMER 5 Output 0 566 Timer5Output1 = 0x2B, // Clock source is TIMER 5 Output 1 567 Timer6Output0 = 0x2C, // Clock source is TIMER 6 Output 0 568 Timer6Output1 = 0x2D, // Clock source is TIMER 6 Output 1 569 Timer7Output0 = 0x2E, // Clock source is TIMER 7 Output 0 570 Timer7Output1 = 0x2F, // Clock source is TIMER 7 Output 1 571 Timer8Output0 = 0x30, // Clock source is TIMER 8 Output 0 572 Timer8Output1 = 0x31, // Clock source is TIMER 8 Output 1 573 Timer9Output0 = 0x32, // Clock source is TIMER 9 Output 0 574 Timer9Output1 = 0x33, // Clock source is TIMER 9 Output 1 575 Timer10Output0 = 0x34, // Clock source is TIMER 10 Output 0 576 Timer10Output1 = 0x35, // Clock source is TIMER 10 Output 1 577 Timer11Output0 = 0x36, // Clock source is TIMER 11 Output 0 578 Timer11Output1 = 0x37, // Clock source is TIMER 11 Output 1 579 Timer12Output0 = 0x38, // Clock source is TIMER 12 Output 0 580 Timer12Output1 = 0x39, // Clock source is TIMER 12 Output 1 581 Timer13Output0 = 0x3A, // Clock source is TIMER 13 Output 0 582 Timer13Output1 = 0x3B, // Clock source is TIMER 13 Output 1 583 Timer14Output0 = 0x3C, // Clock source is TIMER 14 Output 0 584 Timer14Output1 = 0x3D, // Clock source is TIMER 14 Output 1 585 Timer15Output0 = 0x3E, // Clock source is TIMER 15 Output 0 586 Timer15Output1 = 0x3F, // Clock source is TIMER 15 Output 1 587 GPIO0 = 0x80, // GPIO #0 is clock source 588 GPIO63 = 0xBF, // GPIO #63 is clock source 589 GPIO95 = 0xDF, // GPIO #95 is clock source 590 GPIO127 = 0xFF, // GPIO #127 is clock source 591 } 592 593 private enum FunctionSelect 594 { 595 Continous = 0x00, 596 Edge = 0x01, 597 Upcount = 0x02, 598 PWM = 0x04, 599 Downcount = 0x06, 600 SinglePattern = 0x0C, 601 RepeatPattern = 0x0D, 602 EventTimer = 0x0E, 603 } 604 605 private enum PadOutput 606 { 607 Timer0Output0 = 0x00, // Output is Timer 0, output 0 608 Timer0Output1 = 0x01, // Output is Timer 0, output 1 609 Timer1Output0 = 0x02, // Output is Timer 1, output 0 610 Timer1Output1 = 0x03, // Output is Timer 1, output 1 611 Timer2Output0 = 0x04, // Output is Timer 2, output 0 612 Timer2Output1 = 0x05, // Output is Timer 2, output 1 613 Timer3Output0 = 0x06, // Output is Timer 3, output 0 614 Timer3Output1 = 0x07, // Output is Timer 3, output 1 615 Timer4Output0 = 0x08, // Output is Timer 4, output 0 616 Timer4Output1 = 0x09, // Output is Timer 4, output 1 617 Timer5Output0 = 0x0A, // Output is Timer 5, output 0 618 Timer5Output1 = 0x0B, // Output is Timer 5, output 1 619 Timer6Output0 = 0x0C, // Output is Timer 6, output 0 620 Timer6Output1 = 0x0D, // Output is Timer 6, output 1 621 Timer7Output0 = 0x0E, // Output is Timer 7, output 0 622 Timer7Output1 = 0x0F, // Output is Timer 7, output 1 623 Timer8Output0 = 0x10, // Output is Timer 8, output 0 624 Timer8Output1 = 0x11, // Output is Timer 8, output 1 625 Timer9Output0 = 0x12, // Output is Timer 9, output 0 626 Timer9Output1 = 0x13, // Output is Timer 9, output 1 627 Timer10Output0 = 0x14, // Output is Timer 10, output 0 628 Timer10Output1 = 0x15, // Output is Timer 10, output 1 629 Timer11Output0 = 0x16, // Output is Timer 11, output 0 630 Timer11Output1 = 0x17, // Output is Timer 11, output 1 631 Timer12Output0 = 0x18, // Output is Timer 12, output 0 632 Timer12Output1 = 0x19, // Output is Timer 12, output 1 633 Timer13Output0 = 0x1A, // Output is Timer 13, output 0 634 Timer13Output1 = 0x1B, // Output is Timer 13, output 1 635 Timer14Output0 = 0x1C, // Output is Timer 14, output 0 636 Timer14Output1 = 0x1D, // Output is Timer 14, output 1 637 Timer15Output0 = 0x1E, // Output is Timer 15, output 0 638 Timer15Output1 = 0x1F, // Output is Timer 15, output 1 639 STimer0 = 0x20, // Output is STimer 0 640 STimer1 = 0x21, // Output is STimer 1 641 STimer2 = 0x22, // Output is STimer 2 642 STimer3 = 0x23, // Output is STimer 3 643 STimer4 = 0x24, // Output is STimer 4 644 STimer5 = 0x25, // Output is STimer 5 645 STimer6 = 0x26, // Output is STimer 6 646 STimer7 = 0x27, // Output is STimer 7 647 Pattern0 = 0x20, // Output is Pattern Output 0 648 Pattern1 = 0x21, // Output is Pattern Output 1 649 Pattern2 = 0x22, // Output is Pattern Output 2 650 Pattern3 = 0x23, // Output is Pattern Output 3 651 Pattern4 = 0x24, // Output is Pattern Output 4 652 Pattern5 = 0x25, // Output is Pattern Output 5 653 Pattern6 = 0x26, // Output is Pattern Output 6 654 Pattern7 = 0x27, // Output is Pattern Output 7 655 Disabled = 0x3F, // Output is disabled 656 } 657 658 private enum Registers : long 659 { 660 Control = 0x000, // Counter/Timer Control 661 Status = 0x004, // Counter/Timer Status 662 GlobalEnable = 0x010, // Counter/Timer Global Enable 663 InterruptEnable = 0x060, // Counter/Timer Interrupts: Enable 664 InterruptStatus = 0x064, // Counter/Timer Interrupts: Status 665 InterruptClear = 0x068, // Counter/Timer Interrupts: Clear 666 InterruptSet = 0x06C, // Counter/Timer Interrupts: Set 667 OutputConfig0 = 0x080, // Counter/Timer Output Config 0 668 OutputConfig1 = 0x084, // Counter/Timer Output Config 0 669 OutputConfig2 = 0x088, // Counter/Timer Output Config 0 670 OutputConfig3 = 0x08C, // Counter/Timer Output Config 0 671 OutputConfig4 = 0x090, // Counter/Timer Output Config 0 672 OutputConfig5 = 0x094, // Counter/Timer Output Config 0 673 OutputConfig6 = 0x098, // Counter/Timer Output Config 0 674 OutputConfig7 = 0x09C, // Counter/Timer Output Config 0 675 OutputConfig8 = 0x0A0, // Counter/Timer Output Config 0 676 OutputConfig9 = 0x0A4, // Counter/Timer Output Config 0 677 OutputConfig10 = 0x0A8, // Counter/Timer Output Config 0 678 OutputConfig11 = 0x0AC, // Counter/Timer Output Config 0 679 OutputConfig12 = 0x0B0, // Counter/Timer Output Config 0 680 OutputConfig13 = 0x0B4, // Counter/Timer Output Config 0 681 OutputConfig14 = 0x0B8, // Counter/Timer Output Config 0 682 OutputConfig15 = 0x0BC, // Counter/Timer Output Config 0 683 OutputConfig16 = 0x0C0, // Counter/Timer Output Config 0 684 OutputConfig17 = 0x0C4, // Counter/Timer Output Config 0 685 OutputConfig18 = 0x0C8, // Counter/Timer Output Config 0 686 OutputConfig19 = 0x0CC, // Counter/Timer Output Config 0 687 OutputConfig20 = 0x0D0, // Counter/Timer Output Config 0 688 OutputConfig21 = 0x0D4, // Counter/Timer Output Config 0 689 OutputConfig22 = 0x0D8, // Counter/Timer Output Config 0 690 OutputConfig23 = 0x0DC, // Counter/Timer Output Config 0 691 OutputConfig24 = 0x0E0, // Counter/Timer Output Config 0 692 OutputConfig25 = 0x0E4, // Counter/Timer Output Config 0 693 OutputConfig26 = 0x0E8, // Counter/Timer Output Config 0 694 OutputConfig27 = 0x0EC, // Counter/Timer Output Config 0 695 OutputConfig28 = 0x0F0, // Counter/Timer Output Config 0 696 OutputConfig29 = 0x0F4, // Counter/Timer Output Config 0 697 OutputConfig30 = 0x0F8, // Counter/Timer Output Config 0 698 OutputConfig31 = 0x0FC, // Counter/Timer Output Config 0 699 PatternAddress = 0x104, // Pattern Address 700 Timer0Control = 0x200, // Counter/Timer Control 701 Timer0 = 0x204, // Counter/Timer 702 Timer0Compare0 = 0x208, // Counter/Timer 0 Primary Comparator 703 Timer0Compare1 = 0x20C, // Counter/Timer 0 Secondary Compare 704 Timer0Mode = 0x210, // Counter/Timer 0 Mode 705 Timer1Control = 0x220, // Counter/Timer Control 706 Timer1 = 0x224, // Counter/Timer 707 Timer1Compare0 = 0x228, // Counter/Timer 1 Primary Comparator 708 Timer1Compare1 = 0x22C, // Counter/Timer 1 Secondary Compare 709 Timer1Mode = 0x230, // Counter/Timer 1 Mode 710 Timer2Control = 0x240, // Counter/Timer Control 711 Timer2 = 0x244, // Counter/Timer 712 Timer2Compare0 = 0x248, // Counter/Timer 2 Primary Comparator 713 Timer2Compare1 = 0x24C, // Counter/Timer 2 Secondary Compare 714 Timer2Mode = 0x250, // Counter/Timer 2 Mode 715 Timer3Control = 0x260, // Counter/Timer Control 716 Timer3 = 0x264, // Counter/Timer 717 Timer3Compare0 = 0x268, // Counter/Timer 3 Primary Comparator 718 Timer3Compare1 = 0x26C, // Counter/Timer 3 Secondary Compare 719 Timer3Mode = 0x270, // Counter/Timer 3 Mode 720 Timer4Control = 0x280, // Counter/Timer Control 721 Timer4 = 0x284, // Counter/Timer 722 Timer4Compare0 = 0x288, // Counter/Timer 4 Primary Comparator 723 Timer4Compare1 = 0x28C, // Counter/Timer 4 Secondary Compare 724 Timer4Mode = 0x290, // Counter/Timer 4 Mode 725 Timer5Control = 0x2A0, // Counter/Timer Control 726 Timer5 = 0x2A4, // Counter/Timer 727 Timer5Compare0 = 0x2A8, // Counter/Timer 5 Primary Comparator 728 Timer5Compare1 = 0x2AC, // Counter/Timer 5 Secondary Compare 729 Timer5Mode = 0x2B0, // Counter/Timer 5 Mode 730 Timer6Control = 0x2C0, // Counter/Timer Control 731 Timer6 = 0x2C4, // Counter/Timer 732 Timer6Compare0 = 0x2C8, // Counter/Timer 6 Primary Comparator 733 Timer6Compare1 = 0x2CC, // Counter/Timer 6 Secondary Compare 734 Timer6Mode = 0x2D0, // Counter/Timer 6 Mode 735 Timer7Control = 0x2E0, // Counter/Timer Control 736 Timer7 = 0x2E4, // Counter/Timer 737 Timer7Compare0 = 0x2E8, // Counter/Timer 7 Primary Comparator 738 Timer7Compare1 = 0x2EC, // Counter/Timer 7 Secondary Compare 739 Timer7Mode = 0x2F0, // Counter/Timer 7 Mode 740 Timer8Control = 0x300, // Counter/Timer Control 741 Timer8 = 0x304, // Counter/Timer 742 Timer8Compare0 = 0x308, // Counter/Timer 8 Primary Comparator 743 Timer8Compare1 = 0x30C, // Counter/Timer 8 Secondary Compare 744 Timer8Mode = 0x310, // Counter/Timer 8 Mode 745 Timer9Control = 0x320, // Counter/Timer Control 746 Timer9 = 0x324, // Counter/Timer 747 Timer9Compare0 = 0x328, // Counter/Timer 9 Primary Comparator 748 Timer9Compare1 = 0x32C, // Counter/Timer 9 Secondary Compare 749 Timer9Mode = 0x330, // Counter/Timer 9 Mode 750 Timer10Control = 0x340, // Counter/Timer Control 751 Timer10 = 0x344, // Counter/Timer 752 Timer10Compare0 = 0x348, // Counter/Timer 10 Primary Comparator 753 Timer10Compare1 = 0x34C, // Counter/Timer 10 Secondary Compare 754 Timer10Mode = 0x350, // Counter/Timer 10 Mode 755 Timer11Control = 0x360, // Counter/Timer Control 756 Timer11 = 0x364, // Counter/Timer 757 Timer11Compare0 = 0x368, // Counter/Timer 11 Primary Comparator 758 Timer11Compare1 = 0x36C, // Counter/Timer 11 Secondary Compare 759 Timer11Mode = 0x370, // Counter/Timer 11 Mode 760 Timer12Control = 0x380, // Counter/Timer Control 761 Timer12 = 0x384, // Counter/Timer 762 Timer12Compare0 = 0x388, // Counter/Timer 12 Primary Comparator 763 Timer12Compare1 = 0x38C, // Counter/Timer 12 Secondary Compare 764 Timer12Mode = 0x390, // Counter/Timer 12 Mode 765 Timer13Control = 0x3A0, // Counter/Timer Control 766 Timer13 = 0x3A4, // Counter/Timer 767 Timer13Compare0 = 0x3A8, // Counter/Timer 13 Primary Comparator 768 Timer13Compare1 = 0x3AC, // Counter/Timer 13 Secondary Compare 769 Timer13Mode = 0x3B0, // Counter/Timer 13 Mode 770 Timer14Control = 0x3C0, // Counter/Timer Control 771 Timer14 = 0x3C4, // Counter/Timer 772 Timer14Compare0 = 0x3C8, // Counter/Timer 14 Primary Comparator 773 Timer14Compare1 = 0x3CC, // Counter/Timer 14 Secondary Compare 774 Timer14Mode = 0x3D0, // Counter/Timer 14 Mode 775 Timer15Control = 0x3E0, // Counter/Timer Control 776 Timer15 = 0x3E4, // Counter/Timer 777 Timer15Compare0 = 0x3E8, // Counter/Timer 15 Primary Comparator 778 Timer15Compare1 = 0x3EC, // Counter/Timer 15 Secondary Compare 779 Timer15Mode = 0x3F0, // Counter/Timer 15 Mode 780 } 781 } 782 } 783