From: Dan White Date: Tue, 6 Nov 2012 20:56:25 +0000 (-0600) Subject: wip X-Git-Tag: bootrom-initial-submission~44 X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=be32b5c6511db7b55eb47e1dbe3a26a4ad59a646;p=430.git wip --- diff --git a/python-lib/calibrate.py b/python-lib/calibrate.py index afda007..5497d49 100644 --- a/python-lib/calibrate.py +++ b/python-lib/calibrate.py @@ -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) - - - - diff --git a/python-lib/test-nco.py b/python-lib/test-nco.py index d461668..2cd173b 100644 --- a/python-lib/test-nco.py +++ b/python-lib/test-nco.py @@ -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() +