Commit 2f9a6d59 authored by Federico Asara's avatar Federico Asara

Files cleanup.

parent e616927c
This diff is collapsed.
h1. ADC testing
This is a collection of programs to measure ADC characteristics
h2. Prerequisites
Python must be installed.
wx-python must be installed. On Ubuntu, you can install them as indicated in the following url:
http://wiki.wxpython.org/InstallingOnUbuntuOrDebian
h2. Execution
<pre>
python adctest.py
</pre>
This diff is collapsed.
doc:
pydoc -w ./adc-oop.py ./adc.py
clean:
rm -f *.pyc *.html
#! /usr/bin/env python
# coding: utf8
__doc__ = """
Interface for the adc ADC characterization module
This is a preliminary spec of the interface to be expected from the
GUI of the ADC characterization environment
Some notes:
- A Signal object packs all the info we may need from a signal, to
wit,
* its raw data vector and, implicitly,
* raw data vector length == number of samples,
* number of bits (size of the integer samples in raw data vector)
* sampling rate
"""
window_types = [
'RECTANGULAR',
'HANN',
'HAMMING',
'TUKEY',
'COSINE',
'LANCZOS',
'BARTLETT_HANN',
]
class Signal(object):
"""a representation of a time-domain sampled signal
"""
def __init__(self, data, nbits, rate):
"""initialize a signal object
data: an array of samples (usually nbits-long words, stored in
a numpy array)
nbits: bit width of the sample values
rate: sampling rate of sample production
"""
self.data = data
self.nbits = nbits
self.rate = rate
def histogram(self):
"""Compute histogram of a sampled signal
The number of bins in the histogram is implicitly given by the number
of bits of the samples: 2**signal.nbits bins.
returns: an array of 2**signal.nbits numbers (frequencies)
"""
def ideal_histogram(self):
"""Produce an ideal vector of frequencies (histogram) for the
nsamples samples of a perfect nbits ADC. Mostly for auxiliary and
display purposes
returns: an array of 2**signal.nbits numbers (frequencies)
"""
def DNL(self):
"""Compute differential non-linearity vector for a given time-domain
signal
returns: a pair (dnl, total) where
- dnl is an array of 2**signal.nbits real values and
- total is a real value (computed from dnl)
"""
def INL(self):
"""Compute integral non-linearity vector for a given time-domain signal
returns: a pair (inl, total) where
- inl is an array of 2**signal.nbits real values and
- total is a real (computed from inl)
"""
def FFT(self, navg, window):
"""Compute the amplitudes (in dB) of the FFT of signal, averaging navg
slices of it and applying window to it
navg: number of signal slices to average
window: a value from a finite list of windows defined in window_types
returns: an FFTSignal object
"""
class FFTSignal(object):
"""a representation of a frequency-domain signal
"""
def __init__(self, fft, dB = None, time_domain = None):
"""initialize an FFTSignal object
fft: array of numeric values of the fft
dB: true when in dB units, false if raw amplitude
time_domain: the original time-domain signal if available, None
otherwise
self.fft = fft
self.dB = dB
self.time_domain = time_domain
"""
def process_gain(self):
"""compute the process gain for a given number of samples
returns: process gain (a number in dB)
"""
def harmonic_peaks(self, max_peaks):
"""peak detector
This auxiliary function computes an array of indices into the fft
array, pointing to the positions of the first max_peaks most
significant peaks
max_peaks: integer (usually in a small range, < 10)
returns: an array of at most max_peak indices into
the fft.fft array
"""
def noise_floor(self):
"""noise floor of a frequency-domain signal
returns: the real value of the fft noise floor
"""
def SFDR(self):
"""spurious free dynamic range
returns: a real number
"""
def SINAD(self):
"""signal to noise and distortion ratio
returns: a real number
"""
def THD(self):
"""total harmonic distortion
fft: FFTSignal object
returns: a real number
"""
def SNR(self):
"""signal-to-noise ratio
returns: a real number
"""
def ENOB(self):
"""effective number of bits
A direct function of the SINAD, relating both scalar values
"""
if __name__ == '__main__':
pass
#! /usr/bin/env python
# coding: utf8
__doc__ = """
Interface for the adc ADC characterization module
This is a preliminary spec of the interface to be expected from the
GUI of the ADC characterization environment
Some notes:
- A Signal object packs all the info we may need from a signal, to
wit,
* its raw data vector and, implicitly,
* raw data vector length == number of samples,
* number of bits (size of the integer samples in raw data vector)
* sampling rate
- The calls requiring an fft array of numbers use an FFTSignal
object containing the array of samples, whether it is in dB or
absolute units, and the original Signal it comes from. The latter
is mostly ignored, except when some alternative algorithms for
harmonic peak detection are used behing THD, SINAD, etc. In
general, an array of numbers can replace this argument type
everywhere, and the passing of a bare array of reals can
be easily accomodated in each function taking an FFTSignal.
- Some function might vary in spec slightly, but changes, if any,
should be minor.
- In particular, the functions taking an FFT as input might well
take a frequency domain signal object FFTSignal as an argument,
allowing us to compute parameters like distortion or the
best-fitting sinewave in the input from that. This would be
transparent to the callers, who can limit themselves to put
an array of real values in the fft.fft field of the fft argument
passed to THD, SINAD, etc. Do not care about this now, though:
it's easy to change if needed.
"""
window_types = [
'RECTANGULAR',
'HANN',
'HAMMING',
'TUKEY',
'COSINE',
'LANCZOS',
'BARTLETT_HANN',
]
class Signal(object):
"""a representation of a time-domain sampled signal
"""
def __init__(self, data, nbits, rate):
"""initialize a signal object
data: an array of samples (usually nbits-long words, stored in
a numpy array)
nbits: bit width of the sample values
rate: sampling rate of sample production
"""
self.data = data
self.nbits = nbits
self.rate = rate
class FFTSignal(object):
"""a representation of a frequency-domain signal
"""
def __init__(self, fft, dB = None, time_domain = None):
"""initialize an FFTSignal object
fft: array of numeric values of the fft
dB: true when in dB units, false if raw amplitude
time_domain: the original time-domain signal if available, None
otherwise
self.fft = fft
self.dB = dB
self.time_domain = time_domain
"""
def histogram(signal):
"""Compute histogram of a sampled signal
The number of bins in the histogram is implicitly given by the number
of bits of the samples: 2**signal.nbits bins.
signal: a Signal object
returns: an array of 2**signal.nbits numbers (frequencies)
"""
def ideal_histogram(nbits, nsamples):
"""Produce an ideal vector of frequencies (histogram) for the
nsamples samples of a perfect nbits ADC. Mostly for auxiliary and
display purposes
nbits: number of bits of the ideal ADC
nsamples: number of samples
returns: an array of 2**signal.nbits numbers (frequencies)
"""
def DNL(signal):
"""
Compute differential non-linearity vector for a given time-domain
signal
signal: a Signal objectA
returns: a pair (dnl, total) where
- dnl is an array of 2**signal.nbits real values and
- total is a real value (computed from dnl)
"""
def INL(signal):
"""Compute integral non-linearity vector for a given time-domain signal
signal: a Signal object
returns: a pair (inl, total) where
- inl is an array of 2**signal.nbits real values and
- total is a real (computed from inl)
"""
def FFT(signal, navg, window):
"""
Compute the amplitudes (in dB) of the FFT of signal, averaging navg
slices of it and applying window to it
signal: a Signal object
navg: number of signal slices to average
window: a value from a finite list of windows defined in window_types
returns: an FFTSignal object
"""
def process_gain(nsamples):
"""compute the process gain for a given number of samples
nsamples: number of samples for computing an FFT
returns: process gain (a number in dB)
"""
def harmonic_peaks(fft, max_peaks):
"""peak detector
This auxiliary function computes an array of indices into the fft
array, pointing to the positions of the first max_peaks most
significant peaks
fft: FFTSignal object
max_peaks: integer (usually in a small range, < 10)
returns: an array of at most max_peak indices into
the fft.fft array
"""
def noise_floor(fft):
"""noise floor of a frequency-domain signal
fft: FFTSignal object
returns: the real value of the fft noise floor
"""
def SFDR(fft):
"""spurious free dynamic range
fft: FFTSignal object
returns: a real number
"""
def SINAD(fft):
"""signal to noise and distortion ratio
fft: FFTSignal object
returns: a real number
"""
def THD(fft):
"""total harmonic distortion
fft: FFTSignal object
returns: a real number
"""
def SNR(fft):
"""signal-to-noise ratio
fft: FFTSignal object
returns: a real number
"""
def ENOB(sinad):
"""effective number of bits
A direct function of the SINAD, relating both scalar values
"""
return (sinad - 1.76) / 6.02
if __name__ == '__main__':
pass
import sys
import time
import threading
from itertools import izip, count
def foreach(f,l,threads=3,return_=False):
"""
Apply f to each element of l, in parallel
"""
if threads>1:
iteratorlock = threading.Lock()
exceptions = []
if return_:
n = 0
d = {}
i = izip(count(),l.__iter__())
else:
i = l.__iter__()
def runall():
while True:
iteratorlock.acquire()
try:
try:
if exceptions:
return
v = i.next()
finally:
iteratorlock.release()
except StopIteration:
return
try:
if return_:
n,x = v
d[n] = f(x)
else:
f(v)
except:
e = sys.exc_info()
iteratorlock.acquire()
try:
exceptions.append(e)
finally:
iteratorlock.release()
threadlist = [threading.Thread(target=runall) for j in xrange(threads)]
for t in threadlist:
t.start()
for t in threadlist:
t.join()
if exceptions:
a, b, c = exceptions[0]
raise a, b, c
if return_:
r = d.items()
r.sort()
return [v for (n,v) in r]
else:
if return_:
return [f(v) for v in l]
else:
for v in l:
f(v)
return
def parallel_map(f,l,threads=3):
return foreach(f,l,threads=threads,return_=True)
if __name__=='__main__':
def f(x):
print x
time.sleep(0.5)
foreach(f,range(10))
def g(x):
time.sleep(0.5)
print x
raise ValueError, x
time.sleep(0.5)
foreach(g,range(10))
* parser error display freezes compiz. Shorten it to 25 lines or less in
the popup
* automatically parse? An Open button and the parse button is not needed
* in general, test all out-of-bounds conditions and deal with errors
properly
* draw some plots with lines (time-domain signal/done), FFT?, INL/DNL?
* keyboard navigation
* use rfft instead of fft
* fix order of FFT windows in the dialog FFT
* zoom and pan viewports (at least time domain and fft)
* fix the issue with the parameters of Kaiser window
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[SIGNAL]
nbits = 16
rate = 123
data = 1
2
3
4
5
-0.0139388910499
0.0756613283641
0.128759127602
0.169575809817
0.244099439553
0.306779721623
0.375048880639
0.425027260066
0.484185545203
0.535421457098
0.591754384546
0.619414359581
0.687367305494
0.730445183176
0.773202705162
0.815470355326
0.844011499105
0.875280563655
0.900282819658
0.926638791334
0.952639501932
0.966977862275
0.969674255213
1.00198945358
0.981079126722
1.007817229
0.997527816021
0.994226242771
0.988549746779
0.968969798004
0.961382701302
0.940630319908
0.921477072425
0.866496012822
0.843734203894
0.817917693515
0.767138189045
0.724103628976
0.676820098275
0.636729241868
0.587238486772
0.547481768193
0.483829299129
0.42766303586
0.361268122452
0.302087025471
0.258784141815
0.182385331159
0.113858537263
0.0668136363639
0.00927897621256
-0.0701149564905
-0.135020225869
-0.18493204501
-0.246262058332
-0.315120604573
-0.379369268698
-0.426213780707
-0.485519591091
-0.537120876094
-0.597022415245
-0.627126718401
-0.691513911185
-0.716619564037
-0.76833225414
-0.802031287717
-0.85216960123
-0.882476561339
-0.891286115932
-0.927169692758
-0.937679159348
-0.961516883106
-0.977622840092
-1.00073607962
-0.997377280586
-0.99872923133
-0.992706267503
-0.996058135359
-0.987415419325
-0.977516994888
-0.953092683785
-0.927896757013
-0.921581038383
-0.873139853179
-0.84335529775
-0.819544059154
-0.777849859037
-0.725212422197
-0.679382760045
-0.64160346947
-0.588515246869
-0.536935656739
-0.484613091446
-0.432437173482
-0.372268373293
-0.300333618858
-0.256697655616
-0.189626702835
-0.123154588856
-0.0660641664756
pure_sin.txt Pure sinewave, A = 2.9, fa = 100, phi = 0, 1MHz, t=0.02s
gaussian_100th.txt Same with 0.01 rms gaussian noise (SNR = 2e2)
gaussian_1000th.txt Same with 0.001 rms gaussian noise (SNR = 2e3)
incoherent.txt Pure sinewave as above, incoherently sampled (t = 0.025s)
incoherent_1000gaussian.txt Same as above with 0.001 rms gaussian noise (SNR = 2e3)
thd_44_7_times.txt Same as above with 0.01 and 0.02 harmonics (SNR = 44.7)
thd_0.1_0.08_n_0.005.txt With 0.1 and 0.08 harmonics and 0.005 gaussian noise
log How these were made
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
1 : import syn
2 : syn.synth(2.9, 100, 0.0, 1000000, 0, 0.02)
3 : s = +
4 : s = _
5 : s
6 : plot s
7 : from matplotlib import pyplot
8 : pyplot.plot(s)
9 : pyplot.show()
10: _ip.magic("save ")
11: help(save)
12: _ip.magic("save ")
13: save(s, 'pure_sin.txt')
14: save(s, 'pure_sin.txt')
15: from numpy import *
16: save(s, 'pure_sin.txt')
17: save('pure_sin.txt', s)
18: _ip.magic("edit pure_sin.txt.npy")
19: help(save)
20: out = file('pure_sin.txt', 'w')
21:
for i in s:
print >>out, i
22: out.close()
23: _ip.system("view pure*")
24: _ip.system("rm pure_sin.txt.npy")
25:
def w(s, f):
out = file(f, 'w')
for i in s:
print >>out, i
out.close()
26:
27:
28:
29: s
30: t
31: syn.synth(2.9, 100, 0.0, 1000000, 0, 0.02)
32: random.randn(len(s))
33:
34:
35: r = 2.9 * 0.001 * random.randn(len(s))
36: s+r
37: sn = s+r
38: w(s, 'gaussian_1000th.txt')
39: plot s
40: w(sn, 'gaussian_1000th.txt')
41: plot s
42: plot = pyplot.plot
43: plot(s)
44: sn = s+r
45: r = 2.9 * 0.01 * random.randn(len(s))
46: sn = s+r
47: w(sn, 'gaussian_100th.txt')
48: plot(sn)
49: r = 2.9 * 0.001 * random.randn(len(s))
50: sn = s+r
51: w(sn, 'gaussian_100th.txt')
52: plot(sn)
53: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
54: sincoh = s
55: w(sincoh, 'incoherent.txt')
56: sincohn = s + 0.001 * 2.9 * random.randn(len(s))
57: w(sincohn, 'incoherent_1000gaussian.txt')
58: plot(sincohn)
59: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
60: s = s + 0.01 * syn.synth(2.9, 300, 0.0, 1000000, 0, 0.025)
61: s = s + 0.02 * syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
62: plot(s)
63: plot(s)
64: plot(s)
65: 1 / sqrt(5)
66: w(s, 'thd_44_7_times.txt')
67: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
68: s = s + 0.1 syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
69: s = s + 0.1 * syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
70: s = s + 0.08 * syn.synth(2.9, 800, 0.0, 1000000, 0, 0.025)
71: s = s + 0.005 * random.randn(len(s))
72: w(s,'thd_0.1_0.08_n_0.005.txt)
73: w(s,'thd_0.1_0.08_n_0.005.txt')
74: help
75: help()
76: #?
77: #?save
78: #?history
79: histogram
80: _ip.magic("history ")
81: _ip.magic("history -h")
82: #?history -
83: _ip.magic("history -f")
84: #?history
85: _ip.magic("history -f log 1")
86: _ip.system(" view log")
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
pure_sin.txt Pure sinewave, A = 2.9, fa = 100, phi = 0, 1MHz, t=0.02s
gaussian_100th.txt Same with 0.01 rms gaussian noise (SNR = 2e2)
gaussian_1000th.txt Same with 0.001 rms gaussian noise (SNR = 2e3)
incoherent.txt Pure sinewave as above, incoherently sampled (t = 0.025s)
incoherent_1000gaussian.txt Same as above with 0.001 rms gaussian noise (SNR = 2e3)
thd_44_7_times.txt Same as above with 0.01 and 0.02 harmonics (SNR = 44.7)
thd_0.1_0.08_n_0.005.txt With 0.1 and 0.08 harmonics and 0.005 gaussian noise
log How these were made
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
from sys import argv
def adj(x):
return round(x/5.0 * (2**15))
src = open(argv[1], "r")
lines = [int(i.split(", ")[-1][:-1], int(argv[5])) for i in src.readlines()]
src.close()
dest = open(argv[2], "w")
dest.write("[SIGNAL]\nnbits = %s\nrate = %s\ndata = " % (argv[3], argv[4]))
dest.writelines('\t%d\n ' % i for i in lines[int(argv[6]):])
dest.close()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
1 : import syn
2 : syn.synth(2.9, 100, 0.0, 1000000, 0, 0.02)
3 : s = +
4 : s = _
5 : s
6 : plot s
7 : from matplotlib import pyplot
8 : pyplot.plot(s)
9 : pyplot.show()
10: _ip.magic("save ")
11: help(save)
12: _ip.magic("save ")
13: save(s, 'pure_sin.txt')
14: save(s, 'pure_sin.txt')
15: from numpy import *
16: save(s, 'pure_sin.txt')
17: save('pure_sin.txt', s)
18: _ip.magic("edit pure_sin.txt.npy")
19: help(save)
20: out = file('pure_sin.txt', 'w')
21:
for i in s:
print >>out, i
22: out.close()
23: _ip.system("view pure*")
24: _ip.system("rm pure_sin.txt.npy")
25:
def w(s, f):
out = file(f, 'w')
for i in s:
print >>out, i
out.close()
26:
27:
28:
29: s
30: t
31: syn.synth(2.9, 100, 0.0, 1000000, 0, 0.02)
32: random.randn(len(s))
33:
34:
35: r = 2.9 * 0.001 * random.randn(len(s))
36: s+r
37: sn = s+r
38: w(s, 'gaussian_1000th.txt')
39: plot s
40: w(sn, 'gaussian_1000th.txt')
41: plot s
42: plot = pyplot.plot
43: plot(s)
44: sn = s+r
45: r = 2.9 * 0.01 * random.randn(len(s))
46: sn = s+r
47: w(sn, 'gaussian_100th.txt')
48: plot(sn)
49: r = 2.9 * 0.001 * random.randn(len(s))
50: sn = s+r
51: w(sn, 'gaussian_100th.txt')
52: plot(sn)
53: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
54: sincoh = s
55: w(sincoh, 'incoherent.txt')
56: sincohn = s + 0.001 * 2.9 * random.randn(len(s))
57: w(sincohn, 'incoherent_1000gaussian.txt')
58: plot(sincohn)
59: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
60: s = s + 0.01 * syn.synth(2.9, 300, 0.0, 1000000, 0, 0.025)
61: s = s + 0.02 * syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
62: plot(s)
63: plot(s)
64: plot(s)
65: 1 / sqrt(5)
66: w(s, 'thd_44_7_times.txt')
67: s = syn.synth(2.9, 100, 0.0, 1000000, 0, 0.025)
68: s = s + 0.1 syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
69: s = s + 0.1 * syn.synth(2.9, 500, 0.0, 1000000, 0, 0.025)
70: s = s + 0.08 * syn.synth(2.9, 800, 0.0, 1000000, 0, 0.025)
71: s = s + 0.005 * random.randn(len(s))
72: w(s,'thd_0.1_0.08_n_0.005.txt)
73: w(s,'thd_0.1_0.08_n_0.005.txt')
74: help
75: help()
76: #?
77: #?save
78: #?history
79: histogram
80: _ip.magic("history ")
81: _ip.magic("history -h")
82: #?history -
83: _ip.magic("history -f")
84: #?history
85: _ip.magic("history -f log 1")
86: _ip.system(" view log")
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment