Skip to content

Commit 8fb225b

Browse files
authored
Merge branch 'dev' into dependabot/pip/pytest-8.3.3
2 parents 0451b20 + 31960ea commit 8fb225b

19 files changed

+626
-92
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
matrix:
1515
platform:
1616
- ubuntu-latest
17-
python-version: ['3.9', '3.10', '3.11', '3.12']
17+
python-version: ['3.10', '3.11', '3.12']
1818

1919
steps:
2020
- uses: actions/checkout@v3

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ python_adc_eval.egg-info
55
dist
66
.ruff_cache
77
.coverage
8+
.secret
89
build

README.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Given an array of values representing the output of an ADC, the spectrum can be
4242
leak=<adjacent bins to filter>,
4343
window=<window type (rectangular/hanning)>,
4444
no_plot=<True/False>,
45-
yaxis=<"power"/"fullscale">
45+
yaxis=<"power"/"fullscale"/"magnitude">,
46+
single_sided=<True/False>
4647
)
4748
4849

adc_eval/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
11
"""Initialization file for module."""
2-
3-
from . import spectrum
4-
from . import converters
5-
from . import signals

adc_eval/adcs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Initialization file for module."""

adc_eval/adcs/basic.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
"""Basic ADC models."""
2+
3+
import numpy as np
4+
5+
6+
def dac(samples, nbits=8, vref=1):
7+
"""Digital to analog converter."""
8+
quants = 2**nbits
9+
dv = vref / quants
10+
return samples * dv
11+
12+
13+
class ADC:
14+
"""
15+
Generic ADC Class.
16+
17+
...
18+
19+
Parameters
20+
----------
21+
nbits : int, default=8
22+
Number of bits for the ADC.
23+
fs : int or float, default=1
24+
Sample rate for the ADC in Hz.
25+
vref : int or float, default=1
26+
Reference level of the ADC in Volts ([0, +vref] conversion range).
27+
seed : int, default=1
28+
Seed for random variable generation.
29+
**kwargs
30+
Extra arguments.
31+
32+
Attributes
33+
-------
34+
vin : float
35+
Sets or returns the current input voltage level. Assumed +/-vref/2 input
36+
vlsb : float
37+
LSB voltage of the converter. vref/2^nbits
38+
noise : float, default=0
39+
Sets or returns the stdev of the noise generated by the converter.
40+
mismatch : float, default=0
41+
Sets or returns the stdev of the mismatch of the converter.
42+
offset : tuple of float, default=(0, 0)
43+
Sets the (mean, stdev) of the offset of the converter.
44+
gain_error : tuple of float, default=(0, 0)
45+
Sets the (mean, stdev) of the gain error of the converter.
46+
distortion : list of float, default=[1]
47+
Sets the harmonic distortion values with index=0 corresponding to HD1.
48+
Example: For unity gain and only -30dB of HD3, input is [1, 0, 0.032]
49+
dout : int
50+
Digital output code for current vin value.
51+
52+
Methods
53+
-------
54+
run_step
55+
56+
"""
57+
58+
def __init__(self, nbits=8, fs=1, vref=1, seed=1, **kwargs):
59+
"""Initialization function for Generic ADC."""
60+
np.random.seed(seed)
61+
self.nbits = nbits
62+
self.fs = fs
63+
self.vref = vref
64+
self.seed = seed
65+
self.err = {"noise": 0, "gain": 0, "dist": [1], "offset": 0, "mismatch": 0}
66+
self.dbits = np.zeros(nbits)
67+
self.dval = 0
68+
69+
@property
70+
def vin(self):
71+
"""Return input value."""
72+
return self._vin
73+
74+
@vin.setter
75+
def vin(self, x):
76+
"""Set the input value."""
77+
x += self.vref / 2
78+
x = max(0, min(x, self.vref))
79+
self._vin = x
80+
81+
@property
82+
def vlsb(self):
83+
"""Return the LSB voltage."""
84+
return self.vref / 2**self.nbits
85+
86+
@property
87+
def noise(self):
88+
"""Return noise status."""
89+
return self.err["noise"]
90+
91+
@noise.setter
92+
def noise(self, stdev):
93+
"""Set noise stdev in Vrms."""
94+
self.err["noise"] = stdev
95+
96+
@property
97+
def mismatch(self):
98+
"""Return noise stdev."""
99+
print("WARNING: 'mismatch' feature not implemented for this class.")
100+
return False
101+
102+
@mismatch.setter
103+
def mismatch(self, stdev):
104+
"""Set mismatch stdev."""
105+
print("WARNING: 'mismatch' feature not implemented for this class.")
106+
pass
107+
108+
@property
109+
def offset(self):
110+
"""Return offset value."""
111+
return self.err["offset"]
112+
113+
@offset.setter
114+
def offset(self, values):
115+
"""Set offset mean and stdev."""
116+
self.err["offset"] = values[0] + values[1] * np.random.randn(1)
117+
118+
@property
119+
def gain_error(self):
120+
"""Return gain error status."""
121+
return self.err["gain"]
122+
123+
@gain_error.setter
124+
def gain_error(self, values):
125+
"""Set gain error mean and stdev."""
126+
self.err["gain"] = values[0] + values[1] * np.random.randn(1)
127+
128+
@property
129+
def distortion(self):
130+
"""Return distortion gains (1st-order indexed)."""
131+
return self.err["dist"]
132+
133+
@distortion.setter
134+
def distortion(self, gains):
135+
"""Set distortion gains (1st-order indexed)."""
136+
self.err["dist"] = gains
137+
138+
@property
139+
def dout(self):
140+
"""Return digital output code."""
141+
return int(self.dval)
142+
143+
def run_step(self):
144+
"""Run a single ADC step."""
145+
vinx = self.vin
146+
dval = int(
147+
min(max(int((2**self.nbits) * vinx / self.vref), 0), 2**self.nbits - 1)
148+
)
149+
bits = [int(x) for x in bin(dval)[2:]]
150+
151+
while len(bits) < self.nbits:
152+
bits.insert(0, 0)
153+
self.dbits = bits
154+
self.dval = dval

adc_eval/converters.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

adc_eval/eval/simulate.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Generic simulator class for adc evaluation."""
2+
3+
import numpy as np
4+
from tqdm import tqdm
5+
6+
7+
class Simulator:
8+
"""Class for handling simulation functions."""
9+
10+
def __init__(self, adc_obj, xarray):
11+
"""Initialize the simulator class."""
12+
self.dval = []
13+
self.adc = adc_obj
14+
self.vin = self.calc_error(xarray)
15+
16+
@property
17+
def out(self):
18+
"""Return output value array."""
19+
return np.array(self.dval)
20+
21+
def calc_error(self, vin):
22+
"""Using the adc obj, calculates global signal error."""
23+
vinx = vin
24+
25+
# First calculate gain error
26+
vinx *= (1 + self.adc.err["gain"]) * self.adc.err["dist"][0]
27+
28+
# Next calculate the harmonic distortion
29+
for index, gain in enumerate(self.adc.err["dist"]):
30+
if index > 0:
31+
vinx += gain * vin ** (index + 1)
32+
33+
# Now add the offset
34+
vinx += self.adc.err["offset"]
35+
36+
# Now add random noise
37+
vinx += self.adc.err["noise"] * np.random.randn(vin.size)
38+
39+
return vinx
40+
41+
def run(self):
42+
with tqdm(
43+
range(len(self.vin)), "RUNNING", unit=" samples", position=0, leave=True
44+
) as pbar:
45+
for xval in self.vin:
46+
self.adc.vin = xval
47+
self.adc.run_step()
48+
self.dval.append(self.adc.dout)
49+
pbar.update()

0 commit comments

Comments
 (0)