-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sampling.cs
85 lines (75 loc) · 3.5 KB
/
Sampling.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System;
namespace CompositeVideoOscilloscope {
public class Sampling {
const int ns = (int)1e9;
readonly int SampleTimeNs;
readonly int SampleTimeNsRoot;
readonly int[] Buffer;
readonly int[] SlopeBuffer;
public Sampling(int[] buffer, double sampleTime) {
Buffer = buffer;
SampleTimeNsRoot = (int)Math.Sqrt(ns * sampleTime);
var bufLen = buffer.Length;
SlopeBuffer = new int[bufLen];
for (int a = 0; a < bufLen - 1; a++) {
SlopeBuffer[a] = (Buffer[a + 1] - Buffer[a]) / SampleTimeNsRoot;
}
SlopeBuffer[bufLen - 1] = SlopeBuffer[bufLen - 2];
SampleTimeNs = (int)(ns * sampleTime);
}
public int RunTrigger(TriggerControls trigger) {
int timeNs = SampleTimeNs;
int triggerVoltage = (int)(1e6 * trigger.Voltage);
for (int idx = 1; idx < Buffer.Length; idx++) {
var currentVoltage = Buffer[idx];
var lastVoltage = Buffer[idx - 1];
bool currentTrigger = currentVoltage > triggerVoltage;
bool lastTrigger = lastVoltage > triggerVoltage;
if (currentTrigger && !lastTrigger && currentVoltage - lastVoltage > trigger.Edge) {
var interpolatedTime = lastVoltage + currentVoltage == 0 ? 0 : InterpolateTime(lastVoltage, currentVoltage, triggerVoltage);
return interpolatedTime + timeNs - SampleTimeNs;
}
timeNs += SampleTimeNs;
}
return 0;
}
private int InterpolateTime(int v0, int v1, int vt) =>
(((vt - v0) << 8) / (v1 + v0)) >> 8;
public void ResetState(SamplingState current, (int t, int v) start, (int t, int v) delta, bool interpolate) {
current.ScreenVoltage = start.v;
current.DeltaScreenVoltage = delta.v;
current.BufPos = start.t / SampleTimeNs;
current.BufPosfraction = start.t % SampleTimeNs / SampleTimeNsRoot;
current.DeltaBufPos = delta.t / SampleTimeNs;
current.DeltaBufPosFraction = delta.t % SampleTimeNs / SampleTimeNsRoot;
current.Interpolation = interpolate;
SetValue(current);
}
public int GetNext(SamplingState current) {
SetValue(current);
current.ScreenVoltage += current.DeltaScreenVoltage;
current.BufPos += current.DeltaBufPos;
current.BufPosfraction += current.DeltaBufPosFraction;
if (current.BufPosfraction <= 0) {
current.BufPosfraction += SampleTimeNsRoot;
current.BufPos--;
} else if (current.BufPosfraction > SampleTimeNsRoot) {
current.BufPosfraction -= SampleTimeNsRoot;
current.BufPos++;
}
return current.Value;
}
private void SetValue(SamplingState current) {
if (current.BufPos < 0) {
current.Value = 8;
} else if (current.BufPos >= Buffer.Length) {
current.Value = 8;
} else if (current.Interpolation) {
var interpolationDelta = SlopeBuffer[current.BufPos] * current.BufPosfraction;
current.Value = current.ScreenVoltage > interpolationDelta + Buffer[current.BufPos] ? 1 : -1;
} else {
current.Value = current.ScreenVoltage > Buffer[current.BufPos] ? 1 : -1;
}
}
}
}