1 //
2 // Copyright (c) 2010-2021 Antmicro
3 //
4 //  This file is licensed under the MIT License.
5 //  Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using System.Collections.Generic;
10 using System.IO;
11 using Antmicro.Renode.Core;
12 using Antmicro.Renode.Core.Structure.Registers;
13 using Antmicro.Renode.Exceptions;
14 using Antmicro.Renode.Logging;
15 using Antmicro.Renode.Utilities;
16 using Antmicro.Renode.Time;
17 using Antmicro.Renode.Peripherals.Bus;
18 using Antmicro.Renode.Peripherals.Timers;
19 using Antmicro.Renode.Peripherals.DMA;
20 using static System.Math;
21 
22 namespace Antmicro.Renode.Peripherals.Analog
23 {
24     public class ADCChannel
25     {
ADCChannel(IPeripheral parent, int channelId)26         public ADCChannel(IPeripheral parent, int channelId)
27         {
28             this.channelId = channelId;
29             this.parent = parent;
30             samples = new Queue<uint>();
31         }
32 
PrepareSample()33         public void PrepareSample()
34         {
35             lock(lockObject)
36             {
37                 if(samples.Count == 0 && bufferedSamples != null)
38                 {
39                     samples.EnqueueRange(bufferedSamples);
40                 }
41 
42                 if(!samples.TryDequeue(out currentSample))
43                 {
44                     currentSample = 0;
45                     parent.Log(LogLevel.Warning, "No more samples available in channel {0}", channelId);
46                 }
47             }
48         }
49 
GetSample()50         public uint GetSample()
51         {
52             lock(lockObject)
53             {
54                 return currentSample;
55             }
56         }
57 
FeedSample(uint sample, int repeat = 1)58         public void FeedSample(uint sample, int repeat = 1)
59         {
60             lock(lockObject)
61             {
62                 if(repeat == -1)
63                 {
64                     bufferedSamples = new uint [] { sample };
65                 }
66                 else
67                 {
68                     bufferedSamples = null;
69                     for(var i = 0; i < repeat; i++)
70                     {
71                         samples.Enqueue(sample);
72                     }
73                 }
74             }
75         }
76 
FeedSample(IEnumerable<uint> samplesCollection, int repeat = 1)77         public void FeedSample(IEnumerable<uint> samplesCollection, int repeat = 1)
78         {
79             lock(lockObject)
80             {
81                 if(repeat == -1)
82                 {
83                     bufferedSamples = samplesCollection;
84                 }
85                 else
86                 {
87                     bufferedSamples = null;
88                     for(var i = 0; i < repeat; i++)
89                     {
90                         samples.EnqueueRange(samplesCollection);
91                     }
92                 }
93             }
94         }
95 
Reset()96         public void Reset()
97         {
98             lock(lockObject)
99             {
100                 bufferedSamples = null;
101                 samples.Clear();
102                 currentSample = 0;
103             }
104         }
105 
ParseSamplesFile(string path)106         public static IEnumerable<uint> ParseSamplesFile(string path)
107         {
108             var localQueue = new Queue<uint>();
109             var lineNumber = 0;
110 
111             try
112             {
113                 using(var reader = File.OpenText(path))
114                 {
115                     var line = "";
116                     while((line = reader.ReadLine()) != null)
117                     {
118                         ++lineNumber;
119                         if(!uint.TryParse(line.Trim(), out var sample))
120                         {
121                             throw new RecoverableException($"Wrong data file format at line {lineNumber}. Expected an unsigned integer number, but got '{line}'");
122                         }
123 
124                         localQueue.Enqueue(sample);
125                     }
126                 }
127             }
128             catch(Exception e)
129             {
130                 if(e is RecoverableException)
131                 {
132                     throw;
133                 }
134 
135                 // this is to nicely handle IO errors in monitor
136                 throw new RecoverableException(e.Message);
137             }
138 
139             return localQueue;
140         }
141 
142         private readonly IPeripheral parent;
143         private readonly int channelId;
144 
145         private object lockObject = new object();
146 
147         // Sample returned when queried
148         private uint currentSample;
149         // Used for implementing repeat, need to store a sequence of samples
150         private IEnumerable<uint> bufferedSamples;
151         // The current sample sequence
152         private readonly Queue<uint> samples;
153     }
154 }
155