1 // 2 // Copyright (c) 2010-2022 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.Threading; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Time; 13 14 namespace Antmicro.Renode.Peripherals 15 { 16 public class PWMTester : IGPIOReceiver, IExternal 17 { PWMTester()18 public PWMTester() 19 { 20 innerLock = new object(); 21 } 22 OnGPIO(int number, bool value)23 public void OnGPIO(int number, bool value) 24 { 25 if(number != 0) 26 { 27 throw new ArgumentException("This tester should be attached by pin 0 only"); 28 } 29 30 if(!TimeDomainsManager.Instance.TryGetVirtualTimeStamp(out var vts)) 31 { 32 return; 33 } 34 35 lock(innerLock) 36 { 37 if(previousEvent != null) 38 { 39 TimeInterval dt; 40 // TODO: Below `if` block is a way to avoid TimeInterval underflow and the resulting exception 41 // that occurs when the OnGPIO comes from a different thread(core) than expected. 42 // This should be fixed by making sure we always get the Timestamp from the correct thread. 43 // Until then the results will be radomly less accurate. 44 if(vts.TimeElapsed > previousEvent.Value.TimeElapsed) 45 { 46 dt = vts.TimeElapsed - previousEvent.Value.TimeElapsed; 47 } 48 else 49 { 50 dt = TimeInterval.Empty; 51 } 52 53 if(value) 54 { 55 // we switch to high, so up to this point it was low 56 LowTicks += dt.Ticks; 57 } 58 else 59 { 60 HighTicks += dt.Ticks; 61 } 62 } 63 previousEvent = vts; 64 } 65 } 66 Reset()67 public void Reset() 68 { 69 lock(innerLock) 70 { 71 LowTicks = 0; 72 HighTicks = 0; 73 previousEvent = null; 74 } 75 } 76 ToString()77 public override string ToString() 78 { 79 return $"HIGH {HighTicks} ({HighPercentage}%) LOW {LowTicks} ({LowPercentage}%)"; 80 } 81 82 public ulong LowTicks { get; private set; } 83 public ulong HighTicks { get; private set; } 84 public double HighPercentage => (double)HighTicks / (HighTicks + LowTicks) * 100; 85 public double LowPercentage => (double)LowTicks / (HighTicks + LowTicks) * 100; 86 87 private readonly object innerLock; 88 private TimeStamp? previousEvent; 89 } 90 } 91