%pylab inline
Populating the interactive namespace from numpy and matplotlib
from __future__ import division
from IPython.core.display import Image
from deltasigma import *
import warnings
warnings.filterwarnings('ignore')
# skip this, this is just to display nice tables.
from itertools import izip_longest
class Table(list):
def _repr_html_(self):
html = ["<table>"]
for row in self:
html.append("<tr>")
for col in row:
try:
float(col)
html.append("<td>%.3f</td>" % col)
except(ValueError):
html.append("<td><b>%s</b></td>" % col)
html.append("</tr>")
html.append("</table>")
return ''.join(html)
np.set_printoptions(suppress=True, precision=3)
Demonstration of the synthesis of an example delta sigma modulator, as done in the MATLAB Delta Sigma Toolbox
, employing its Python port deltasigma
.
The Noise Transfer Function (NTF) is synthesized for a 5th-order, low-pass modulator, having the following characteristics:
32
,For this example modulator, we select to implement the CRFB topology -- see below, for order being odd -- with a single feed-in, ie $b_n = 0\ \forall n > 1$ .
Image(url='http://python-deltasigma.readthedocs.org/en/latest/_images/CRFB.png', retina=True)
order = 5
osr = 32
nlev = 2
f0 = 0.
Hinf = 1.5
form = 'CRFB'
ntf = synthesizeNTF(order, osr, 2, Hinf, f0) # Optimized zero placement
print "Synthesized a %d-order NTF, with roots:\n" % order
print " Zeros:\t\t\t Poles:"
for z, p in zip(ntf[0], ntf[1]):
print "(%f, %fj)\t(%f, %fj)" % (np.real(z), np.imag(z), np.real(p), np.imag(p))
print ""
print "The NTF transfer function has the following expression:\n"
print pretty_lti(ntf)
print ""
Synthesized a 5-order NTF, with roots: Zeros: Poles: (1.000000, 0.000000j) (0.806557, -0.119823j) (0.998603, 0.052839j) (0.806557, 0.119823j) (0.998603, -0.052839j) (0.898071, -0.219819j) (0.996045, 0.088847j) (0.898071, 0.219819j) (0.996045, -0.088847j) (0.777767, 0.000000j) The NTF transfer function has the following expression: (z^2 - 1.992z + 0.9999) (z^2 - 1.997z + 1) (z - 1) ------------------------------------------------------------- (z^2 - 1.613z + 0.665) (z^2 - 1.796z + 0.8549) (z - 0.7778)
plotPZ(ntf, showlist=True)
a, g, b, c = realizeNTF(ntf, form)
b = np.hstack(( # Use a single feed-in for the input
np.atleast_1d(b[0]),
np.zeros((b.shape[0] - 1, ))
))
ABCD = stuffABCD(a, g, b, c, form)
print "ABCD Matrix:"
print ABCD
ABCD Matrix: [[ 1. 0. 0. 0. 0. 0.001 -0.001] [ 1. 1. -0.003 0. 0. 0. -0.008] [ 1. 1. 0.997 0. 0. 0. -0.063] [ 0. 0. 1. 1. -0.008 0. -0.244] [ 0. 0. 1. 1. 0.992 0. -0.802] [ 0. 0. 0. 0. 1. 0. 0. ]]
DocumentNTF(ABCD, osr, f0)
f = gcf()
f.set_size_inches((15, 6))
figure(figsize=(15,8))
PlotExampleSpectrum(ntf, M=1, osr=osr, f0=f0)
snr, amp = simulateSNR(ntf, osr, None, f0, nlev)
figure(figsize=(15,8))
if nlev == 2:
snr_pred, amp_pred, k0, k1, se = predictSNR(ntf, osr)
plot(amp_pred, snr_pred, '-', label='predicted')
hold(True)
plot(amp, snr,'o-.g', label='simulated')
xlabel('Input Level (dBFS)')
ylabel('SQNR (dB)')
peak_snr, peak_amp = peakSNR(snr, amp)
msg = 'peak SQNR = %4.1fdB \n@ amp = %4.1fdB ' % (peak_snr, peak_amp)
text(peak_amp-10,peak_snr,msg, horizontalalignment='right', verticalalignment='center');
msg = 'OSR = %d ' % osr
text(-2, 5, msg, horizontalalignment='right');
hold(False)
figureMagic([-100, 0], 10, None, [0, 100], 10, None, [12, 6], 'Time-Domain Simulations')
legend(loc=2);
Keep the integrator outputs within their working range -- to avoid waveform clipping and instabilities.
The ABCD matrix is scaled opportunely, then the effectiveness of the dynamic range scaling is verified and the state maxima are plotted for different amplitudes.
print 'Doing dynamic range scaling... ',
ABCD0 = ABCD.copy()
ABCD, umax, S = scaleABCD(ABCD0, nlev, f0)
print 'Done.'
print "Maximum input magnitude: %.3f" % umax
Doing dynamic range scaling... Done. Maximum input magnitude: 0.583
print 'Verifying dynamic range scaling... ',
u = np.linspace(0, 0.95*umax, 30)
N = 1e4
N0 = 50
test_tone = np.cos(2*np.pi*f0*np.arange(N))
test_tone[:N0] = test_tone[:N0]*(0.5 - 0.5*np.cos(2*np.pi/N0*np.arange(N0)))
maxima = np.zeros((order, u.shape[0]))
for i in np.arange(u.shape[0]):
ui = u[i]
v, xn, xmax, y = simulateDSM(ui*test_tone, ABCD, nlev)
maxima[:, i] = xmax[:, 0]
if (xmax > 1e2).any():
print 'Warning, umax from scaleABCD was too high.'
umax = ui
u = u[:i]
maxima = maxima[:, :i]
break
print 'Done.'
print "Maximum DC input level: %.3f" % umax
Verifying dynamic range scaling... Done. Maximum DC input level: 0.583
colors = get_cmap('jet')(np.linspace(0, 1.0, order))
hold(True)
for i in range(order):
plot(u,maxima[i,:], 'o-', color=colors[i], label='State %d' % (i+1))
grid(True)
#text(umax/2, 0.05, 'DC input', horizontalalignment='center', verticalalignment='center')
figureMagic([0, umax], None, None, [0, 1] , 0.1, 2, [12, 6], 'State Maxima')
xlabel('DC input')
ylabel('Maxima')
legend(loc='best');
a, g, b, c = mapABCD(ABCD, form)
adc = {
'order':order,
'osr':osr,
'nlev':nlev,
'f0':f0,
'ntf':ntf,
'ABCD':ABCD,
'umax':umax,
'peak_snr':peak_snr,
'form':form,
'coefficients':{
'a':a,
'g':g,
'b':b,
'c':c
}
}
t = Table()
ilabels = ['#1', '#2', '#3', '#4', '#5', '#6']
t.append(['Coefficients', 'DAC feedback', 'Resonator feedback',
'Feed-in', 'Interstage'])
t.append(['', 'a(n)', 'g(n)', ' b(n)', ' c(n)'])
[t.append(x) for x in izip_longest(ilabels,
adc['coefficients']['a'].tolist(),
adc['coefficients']['g'].tolist(),
adc['coefficients']['b'].tolist(),
adc['coefficients']['c'].tolist(), fillvalue="")]
t
Coefficients | DAC feedback | Resonator feedback | Feed-in | Interstage |
a(n) | g(n) | b(n) | c(n) | |
#1 | 0.100 | 0.015 | 0.100 | 0.137 |
#2 | 0.170 | 0.018 | 0.000 | 0.191 |
#3 | 0.213 | 0.000 | 0.384 | |
#4 | 0.363 | 0.000 | 0.440 | |
#5 | 0.365 | 0.000 | 1.530 | |
#6 | 0.000 |
#%install_ext http://raw.github.com/jrjohansson/version_information/master/version_information.py
%load_ext version_information
%reload_ext version_information
%version_information numpy, scipy, matplotlib, deltasigma
Software | Version |
---|---|
Python | 2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)] |
IPython | 3.2.1 |
OS | Darwin 14.4.0 x86_64 i386 64bit |
numpy | 1.9.2 |
scipy | 0.16.0 |
matplotlib | 1.4.3 |
deltasigma | 0.2.2 |
Fri Aug 07 16:22:06 2015 CEST |