wip
authorDan White <dan@whiteaudio.com>
Tue, 6 Nov 2012 20:56:25 +0000 (14:56 -0600)
committerDan White <dan@whiteaudio.com>
Tue, 6 Nov 2012 20:56:25 +0000 (14:56 -0600)
python-lib/calibrate.py
python-lib/test-nco.py

index afda007e7c0f886f52ee0a3826bd0a7b89eb68cf..5497d49ddc60af6bc82267db84dd5f5b85bf9d44 100644 (file)
@@ -313,16 +313,6 @@ def chain_offsets(values, converged, mux_offset, verbose=True):
             if converged[iq, hi] == 1:
                 chain.h[hi].ota[iq].offset = int(values[iq, hi])
 
-        #for i,n in enumerate(values[0]):
-            ## only update flagged values
-            #if converged[0, i]:
-                #chain.h[i].otaA.offset = int(n)
-
-        #for i,n in enumerate(values[1]):
-            ## only update flagged values
-            #if converged[0, i]:
-                #chain.h[i].otaB.offset = int(n)
-
     chain.write()
     sleep(1.0) # TODO: better delay value?
 
@@ -337,6 +327,116 @@ def chain_offsets(values, converged, mux_offset, verbose=True):
 
 
 
+def amux_a_offset(x, c, verbose=True):
+    #xi = int(x[0])
+    xi = int(x)
+    amux.otaA.offset = xi
+    amux.write()
+    sleep(MUX_CAL_DELAY)
+    adc.read()
+    values = []
+    for i in range(N_SAMPLES):
+        values.append(offset2signed(adc.read(), 16))
+        sleep(SAMPLE_DELAY)
+    mv = mean(values)
+    #if verbose: print tpx(xi), tplot(mv)
+    return array((mv,))
+
+def amux_b_offset(x, c, verbose=True):
+    xi = int(x)
+    amux.otaB.offset = xi
+    amux.write()
+    sleep(MUX_CAL_DELAY)
+    adc.read()
+    values = []
+    for i in range(N_SAMPLES):
+        values.append(offset2signed(adc.read(), 16))
+        sleep(SAMPLE_DELAY)
+    mv = mean(values)
+    #if verbose: print tpx(xi), tplot(mv)
+    return array((mv,))
+
+
+def arb_outputs(converged, verbose=True):
+    adc.triggerMode(adc.MODE_IDLE)
+    adc.mux(6) #amux.otaA, arb_out0
+    adc.fifo(1)
+    adc.triggerMode(adc.MODE_MANUAL_MANUAL)
+
+    outs = zeros(converged.shape)
+    #each harmonic
+    for i in range(outs.shape[1]):
+        # skip evaluating converged channel groups
+        # output values are ignored for these channels
+        if sum(converged[:,i]) == 0:
+            outs[0, i] = 0.0
+            outs[1, i] = 0.0
+            if verbose: print 'skipping converged channel pair: %02i' % i
+            continue
+
+        amux.selA = i
+        amux.selB = i
+        amux.write()
+        sleep(MUX_SETTLE_DELAY)
+
+        # I, Q
+        for j in range(2):
+            # also ignore individual channel
+            # (small speedup, but it all helps...)
+            if converged[j, i] == 0:
+                outs[j, i] = 0.0
+                if verbose: print 'skipping converged channel %i %s' % (i, ('A','B')[j])
+                continue
+
+            adc.mux(6+j) #vouts on channels 6,7
+            adc.read()
+            values = []
+            v = offset2signed(adc.read(), 16)
+            values.append(v)
+            for k in range(N_SAMPLES-1):
+                sleep(SAMPLE_DELAY)
+                v = offset2signed(adc.read(), 16)
+                values.append(v)
+            if N_SAMPLES >= 2:
+                mv = mean(values[-1*min(10, N_SAMPLES):-1]) #TODO
+            else:
+                mv = values[0]
+            outs[j, i] = mv
+
+    if verbose:
+        print '*** measured outputs: ***'
+        print outs
+
+    return outs
+
+
+
+def arb_offsets(values, converged, mux_offset, verbose=True):
+    if verbose:
+        print
+        print '*** sending values: ***'
+        print values
+
+    for hi in range(16):
+        for iq in range(2):
+            # only update flagged values
+            if converged[iq, hi] == 1:
+                arb.h[hi].ota[iq].offset = int(values[iq, hi])
+
+    arb.write()
+    sleep(1.0) # TODO: better delay value?
+
+    outs = arb_outputs(converged, verbose=verbose)
+
+    # remove measured residual offset from mux to "see through" the pad buffer
+    for i in range(2):
+        outs[i,:] -= mux_offset[i]
+
+    return outs
+
+
+
+
 dac.vina(1.25)
 dac.vinb(1.25)
 dac.vcmi(1.25)
@@ -357,9 +457,142 @@ adc.triggerMode(adc.MODE_MANUAL_MANUAL)
 
 
 
-import datetime as dt
+def calibrate(name, elements=None, verbose=True):
+    """Calibrate the block identified by name.  If ids is specified, this is
+    an element or list of the specific elements to be calibrated, leaving
+    others alone.
+
+    returns: (offsets, stats)
+
+    NB: The calibration routines only modify the relevant ota.offset values,
+    and sets the .cal bit for the chains.  All other settings (.fast, cint,
+    etc) are left un-touched.
+    """
+    #all amplifiers share this
+    limits = (-128, 127)
+
+    #
+    # Main 48-channel chain
+    #
+    if name == 'chain':
+        N_CHANNELS = 48
+        def func(values, converging):
+            return chain_offsets(
+                    values,
+                    converging,
+                    (int(mux.otaA.offset), int(mux.otaB.offset))
+                    )
+
+        #setup initial guess, just use the current values
+        x0 = zeros((2, N_CHANNELS), dtype=int)
+        for i in range(N_CHANNELS):
+            for j in range(2):
+                x0[j,i] = chain.h[i].ota[j].offset
+        offsets, stats = secant_opt(func, x0, limits,
+                elements=elements, verbose=verbose)
+
+    #
+    # Main pad buffer + mux
+    #
+    elif name == 'mux':
+        #save mux state
+        old_mode = [mux.ota[i].mode for i in range(2)]
+
+        mux.otaA.mode = mux.otaA.CAL_CMP
+        mux.otaB.mode = mux.otaB.CAL_CMP
+        mux.write()
+        adc.mux(4)
+
+        def func(values, converging):
+            outA = mux_a_offset(values[0], converging[0], verbose)
+            outB = mux_b_offset(values[1], converging[1], verbose)
+            out = zeros((2,))
+            out[0] = outA
+            out[1] = outB
+            return out
+            return array([outA, outB])
+
+        #setup initial guess, just use the current values
+        x0 = zeros((2,), dtype=int)
+        for i in range(2):
+            x0[i] = int(mux.ota[i].offset)
+
+        offsets, stats = secant_opt(func, x0, limits,
+                elements=elements, verbose=verbose)
+
+        #restore mux state
+        for i,mode in enumerate(old_mode):
+            mux.ota[i].mode = mode
+        mux.write()
+
+    #
+    # Secondary arbitrary function, 16 channels
+    #
+    if name == 'arb':
+        N_CHANNELS = 16
+        def func(values, converging):
+            return arb_offsets(
+                    values,
+                    converging,
+                    (int(amux.otaA.offset), int(amux.otaB.offset))
+                    )
+
+        #setup initial guess, just use the current values
+        x0 = zeros((2, N_CHANNELS), dtype=int)
+        for i in range(N_CHANNELS):
+            for j in range(2):
+                x0[j,i] = arb.h[i].ota[j].offset
+        offsets, stats = secant_opt(func, x0, limits,
+                elements=elements, verbose=verbose)
+
+    #
+    # Secondary pad buffer + mux
+    #
+    elif name == 'amux':
+        #save mux state
+        old_mode = [amux.ota[i].mode for i in range(2)]
+
+        amux.otaA.mode = amux.otaA.CAL_CMP
+        amux.otaB.mode = amux.otaB.CAL_CMP
+        amux.write()
+        adc.mux(6)
+
+        def func(values, converging):
+            outA = amux_a_offset(values[0], converging[0], verbose)
+            outB = amux_b_offset(values[1], converging[1], verbose)
+            out = zeros((2,))
+            out[0] = outA
+            out[1] = outB
+            return out
+            return array([outA, outB])
+
+        #setup initial guess, just use the current values
+        x0 = zeros((2,), dtype=int)
+        for i in range(2):
+            x0[i] = int(amux.ota[i].offset)
+
+        offsets, stats = secant_opt(func, x0, limits,
+                elements=elements, verbose=verbose)
+
+        #restore mux state
+        for i,mode in enumerate(old_mode):
+            amux.ota[i].mode = mode
+        amux.write()
+
+    else:
+        print 'ERROR: unknown name %s' % name
+
+    return (offsets, stats)
+
+
+
+
+
+
+
 
 while False:
+    import datetime as dt
     if 1:
         mux.otaA.mode = mux.otaA.CAL_BUF
         mux.otaA.fast = 1
@@ -455,72 +688,4 @@ while False:
 
 
 
-def calibrate(name, elements=None, verbose=True):
-    """Calibrate the block identified by name.  If ids is specified, this is
-    an element or list of the specific elements to be calibrated, leaving
-    others alone.
-
-    returns: (offsets, stats)
-
-    NB: The calibration routines only modify the relevant ota.offset values,
-    and sets the .cal bit for the chains.  All other settings (.fast, cint,
-    etc) are left un-touched.
-    """
-    #all amplifiers share this
-    limits = (-128, 127)
-
-    if name == 'chain':
-        def func(values, converging):
-            return chain_offsets(
-                    values,
-                    converging,
-                    (int(mux.otaA.offset), int(mux.otaB.offset))
-                    )
-
-        #setup initial guess, just use the current values
-        x0 = zeros((2, N_CHANNELS), dtype=int)
-        for i in range(N_CHANNELS):
-            for j in range(2):
-                x0[j,i] = chain.h[i].ota[j].offset
-        offsets, stats = secant_opt(func, x0, limits,
-                elements=elements, verbose=verbose)
-    elif name == 'mux':
-        #save mux state
-        old_mode = [mux.ota[i].mode for i in range(2)]
-
-        mux.otaA.mode = mux.otaA.CAL_CMP
-        mux.otaB.mode = mux.otaB.CAL_CMP
-        mux.write()
-        adc.mux(4)
-
-        def func(values, converging):
-            outA = mux_a_offset(values[0], converging[0], verbose)
-            outB = mux_b_offset(values[1], converging[1], verbose)
-            out = zeros((2,))
-            out[0] = outA
-            out[1] = outB
-            return out
-            return array([outA, outB])
-
-        #setup initial guess, just use the current values
-        x0 = zeros((2,), dtype=int)
-        for i in range(2):
-            x0[i] = int(mux.ota[i].offset)
-
-        offsets, stats = secant_opt(func, x0, limits,
-                elements=elements, verbose=verbose)
-
-        #restore mux state
-        for i,mode in enumerate(old_mode):
-            mux.ota[i].mode = mode
-        mux.write()
-
-    else:
-        print 'ERROR: unknown name %s' % name
-
-    return (offsets, stats)
-
-
-
-
 
index d461668320368282ee0de077c4aa1b920e6a134a..2cd173b7f65bc7c9429d0a08f6a03cf54a35ca0b 100644 (file)
@@ -1,12 +1,16 @@
 #!/usr/bin/env python
 
+import IPython
 from time import sleep
 
 import devboard as dev
 dev.init_devboard(1)
 
 # requires devboard be already initialized
-from calibrate import calibrate
+from calibrate import calibrate as cal
+
+
+do_shell = True
 
 
 if 0:
@@ -15,3 +19,13 @@ if 0:
 
     print 'Calibrating chain.'
     calibrate('chain')
+    print '%-10s %8.2f uA' % (name, 1e6*i)
+
+
+
+##############################################################################
+# drop into an IPython shell
+#
+if do_shell:
+    IPython.embed()
+