In this test the charge channels readout and triggering will be tested.
- First a single trace from each channel will be read and plotted
- Then, you should connect a signal generator to the charge channel input in the miniBob, the code will use the trigger to locate, read and plot the trace
Note: if this is an exported file you can click on plots and comments to toggle display the source code.
%pylab inline
import DCRC_controls
import Trigger_Simulation.trigger_simulation as trig_sim
import trig_controls
import picoscope
import ipywidgets as widgets
from test_utilities import *
# Set up some plotting defaults
matplotlib.rc('figure', figsize=(6, 5*(4/6)), dpi=144)
matplotlib.rc('font', size=6)
matplotlib.rc('legend', scatterpoints=1)
colors=['#af1b1b','#c51e1e','#db2222',#red
'#db7e22','#db7e22','#db7e22',#orange
'#c5c51e','#dbdb22','#e0e036',#yellow
'#72c51e','#8be036','#a5e762',#green
'#1b65af','#227edb','#4c98e3']#blue
subcolors= ['#e98a72','#ec9b86','#f2bcae',
'#ecce86', '#efd69a','#f2deae',
'#ffc293','#ffd0ac','#ffdfc6',
'#91c588','#b1d5aa','#c1debb',
'#6672b4','#8891c5','#aab1d5']
width=4
nn=0
Initiate connection and run some quick tests. The board is already assumed to be 'set-up' (likely with drec 1), but not fixed here to keep flexibility. It is even possible to execute that or any requirement in the "Command Machine" Cell.
DCRC = DCRC_controls.DCRC('165.91.180.60', 5003)
DCRC.open()
DCRC.write_reg(0x20, 0x10) # Make this DCRC the bus master
DCRC.enable_ADC() # Turn on digitization
# Check serial number etc.
IDinfo = DCRC.ID()
for key in IDinfo.keys():
print('% 13s: % 15s'%(key, IDinfo[key]))
print()
print("FPGA Firmware version string:", DCRC.firmware_version())
# Connect to the picoscope
scope = picoscope.picoscope()
scope.open()
times = linspace(0, 2*pi, 1000)
scope.setup_AWG(10000*sin(times), shots=-1)
scope.trigger_AWG()
DCRC.DCRC.send(b"drec 0\r")
DCRC.write_reg(0x440, 0)
time.sleep(0.5)
DCRC.DCRC.recv(32768)
pass
#print(DCRC.DCRC.recv(32768).decode())
qchan=12 # channel to read (12 to 15) Q0:15 Q1:14 Q2:13 Q3:12
nwds=20*4096 # number of words to read (decimal, will convert to hex)
#time.sleep(0.5)
DCRC.reset_ADC()
time.sleep(0.25)
thpulse=DCRC.readout(qchan, nwds, offset=8192)
fig = PlotPulse([thpulse], "Test Charge Trace", plabels=['Q'+str(qchan)])
Disconnect picoscope from DCRC
%%time
DCRC.write_reg(0x402, 0)
for qch in [0,1,2,3]:
#for qch in [0]:
figure()
for setting in [0x0000, 0xc000, 0xf000, 0xffff]:
DCRC.reset_ADC()
time.sleep(0.25)
DCRC.write_reg(0x600 + qch, setting)
time.sleep(0.25)
dat = DCRC.readout(12 + qch, 2*625000, offset=128)
plot(arange(2*625000)/2.5e6, dat)
time.sleep(1)
xlabel('Time [s]')
ylabel('Charge ch %d trace [arb.]'%qch)
DCRC.DCRC.send(b"drec 0\r")
time.sleep(0.5)
DCRC.DCRC.recv(32768)
pass
#print(DCRC.DCRC.recv(32768).decode())
DCRC.write_reg(0x402, 1) # Enable Test Signal
DCRC.write_reg(0x403, 1)
DCRC.write_reg(0x404, 0)
#DCRC.write_reg(0x405, 0x002)
DCRC.write_reg(0x410, 0)
DCRC.write_reg(0x411, 0x900) # Test signal frequency (MSB)
DCRC.write_reg(0x440, 1) # Enable Charge Pulse Test
DCRC.write_reg(0x441, 0) # Select one charge channel to test:0, 1, 2, 3
DCRC.write_reg(0x442, 0x500) # set the amplitute: 0x000-0xFFF(0mV-5V in steps of 1.2mV)
time.sleep(0.5)
qchan=12
# channel to read (12 to 15)
nwds=16384*4 #48*4096 # number of words to read (decimal, will convert to hex)
#time.sleep(0.5)
DCRC.reset_ADC()
time.sleep(0.25)
thpulse=DCRC.readout(qchan, nwds, offset=8192)
fig = PlotPulse([thpulse], "Test Charge Trace_Pulser", plabels=['Q'+str(qchan)])
LC_coeffs = zeros((4,16), 'i8')
LC_coeffs[0,qchan] = -127 # only one phonon channel
raw_FIR_coeffs = zeros((4, 1024))
raw_FIR_coeffs[0, 0:10] = 3 # 10 baseline samples
raw_FIR_coeffs[0, 10:13] = -10 # 3 signal samples
FIR_coeffs = asarray(raw_FIR_coeffs * 3276, 'i8')
trig = trig_sim.Trigger(bits_phonon=16, bits_charge=16,
phonon_DF_R=16, phonon_DF_N=3, phonon_DF_M=1, phonon_start=0,
charge_DF_R=64, charge_DF_N=3, charge_DF_M=1, charge_start=0,
LC_coeffs=LC_coeffs, LC_bits_out=46,
LC_bits_coeff=8, LC_discard_MSBs=[0,0,0,0],
FIR_coeffs=FIR_coeffs, FIR_bits_out=32,
FIR_bits_coeff=16, FIR_discard_MSBs=[0,0,0,0],
ThL_selectors=array([0,1,1,1,1,1,1,1], dtype='uint'),
ThL_activation_thresholds = 32767*ones(8, int),
ThL_deactivation_thresholds = zeros(8, int),
PS_max_window_lengths=(2**31 - 1)*ones(4, dtype='uint'),
PS_saturated_pulse_offsets=zeros(4, dtype='uint'),
TrL_selectors=array([0,1,1,1,1,1,1,1], dtype='uint'),
TrL_enables=array([1,0,0,0,0,0,0,0], dtype=bool),
TrL_requires=zeros((8,16), bool), TrL_vetos=zeros((8, 16), bool),
TrL_prescales=ones(8, dtype='float'))
trig.ThL.ThLs[0].set_thresholds(9000, 0)
tc = trig_controls.Trig_Controls(DCRC, trig, verbose=False)
def get_atleast1_trig():
trigs = array([])
trys = 0
while len(trigs) == 0:
if trys >= 10:
raise RuntimeError("Tried %d times, but recorded no triggers"%trys)
DCRC.clear_trig_FIFO()
scope.trigger_AWG()
time.sleep(0.25)
trigs = DCRC.read_trig_FIFO()
trys += 1
#DCRC.disable_ADC()
return trigs
def readout_trig(one_trigger):
downsample_offset = (one_trigger['timestamp']-7) % 16 + 7
dat = [asarray(DCRC.readout(i, 16384, offset=one_trigger['timestamp'] - 8192 - downsample_offset), 'i8')
for i in range(12)]
dat.extend([asarray(DCRC.readout(i, 16384*4, offset=one_trigger['timestamp'] - 8192 - downsample_offset), 'i8')
for i in range(12,16)])
#dat.extend([zeros(4*16384, 'i8')]*4)
trig.reset()
trig.through_FIR.send(dat)
FIRdat = trig.through_FIR.send(dat)
return dat, FIRdat
DCRC.reset_ADC()
#DCRC.write_reg(0x0, 0x1)
# Configure the trigger for non-inverted pulses
qchan=12
LC_coeffs = zeros((4,16), 'i8')
LC_coeffs[0,qchan] = -127
trig.set_FIR_coeffs(FIR_coeffs)
tc.configure_trigger()
time.sleep(0.75)
trigs = get_atleast1_trig()
print('trigs:\n', trigs)
datatrigs = trigs[(trigs['trigword']!=0)&(trigs['trigbits']!=255)]
print('datatrigs:', 'Amplitude of datatrigs[0]', datatrigs[0]['amplitude'],'\n', datatrigs)
dat, FIRdat = readout_trig(datatrigs[0])
print('FIRdat:','(Max)', amax(FIRdat[0]),'\n','FIRdat[0]',FIRdat[0])
#asarray(thpulse, dtype='i8')
thpulses=[zeros(16384, dtype='i8')]*12 + [zeros(16384*4, dtype='i8')]*3 + [asarray(thpulse, dtype='i8')]
#print('thpulses:\n', thpulses)
#trig.reset()
FIRdat1=trig.through_FIR.send(thpulses)
print('FIRdat1:','(Max)', amax(FIRdat1[0]),'(Min)',amin(FIRdat[0]),'\n','FIRdat1[0]',FIRdat1[0])
assert amax(FIRdat[0]) == datatrigs[0]['amplitude']
PlotPulse([dat[qchan]], plttitle='Triggered charge pulse')
show()
close()
PlotPulse([FIRdat[0]], plttitle='FIR output')
show()
close()
#qchs=[12,15,14,13] # for RevE SN8
qchs=[12,15,14,13]
trig.set_FIR_coeffs(FIR_coeffs)
qch_pulses=zeros((len(qchs),65536), '>i2')
qchFIR_pulses = zeros((4,1024), '>i2')
for ii,tchan in enumerate(qchs):
LC_coeffs = zeros((4, 16), 'i8')
LC_coeffs[0, tchan] = -127
trig.set_LC_coeffs(LC_coeffs)
tc.configure_trigger()
time.sleep(0.25)
DCRC.write_reg(0x441, ii)
time.sleep(0.25)
nwds=16384*4 #48*4096 # number of words to read (decimal, will convert to hex)
DCRC.reset_ADC()
time.sleep(0.25)
thpulse=DCRC.readout(tchan, nwds, offset=8192)
trigs = get_atleast1_trig()
datatrigs = trigs[(trigs['trigword']!=0)&(trigs['trigbits']!=255)]
dat, FIRdat = readout_trig(datatrigs[0])
#thpulses=[zeros(16384, dtype='i8')]*12 + [zeros(16384*4, dtype='i8')]*3 + [asarray(thpulse, dtype='i8')]
#FIRdat1=trig.through_FIR.send(thpulses)
assert amax(FIRdat[0]) == datatrigs[0]['amplitude']
qch_pulses[ii] = dat[tchan]
qchFIR_pulses[ii] = FIRdat[0]
channel_tabs = widgets.Tab()
display(channel_tabs)
channel_tabs.children = [widgets.Output() for i in range(len(qchs))]
for ii, tchan in enumerate(qchs):
channel_tabs.set_title(ii, 'qCh.%d'%tchan)
with channel_tabs.children[ii]:
PlotPulse(qch_pulses[ii], plttitle='Triggered Charge Pulse. Charge Channel %d'%tchan)
show()
close()
PlotPulse(qchFIR_pulses[ii], plttitle='FIR output. Charge Channel %d'%tchan)
show()
close()
@vectorize
def make_charge_pulse(t):
if t < 0:
return 0.
else:
return exp(-t/650e-6) - exp(-t/100e-6)
charge_times = (arange(16384)-8192) * 32 / 2.5e6
#charge_times = (arange(16384) - 8192) / 625e3
charge_pulse = make_charge_pulse(charge_times)
charge_pulse /= amax(charge_pulse)
plot(charge_pulse)
# Define configurations for reading input signal
qchan=15 # channel to read (0 to 11)
nwds=8192 # number of words to read (decimal, will convert to hex)
nqchans=4 # number of charge channels
DCRC.DCRC.send(b"drec 0\r")
time.sleep(0.5)
DCRC.DCRC.recv(32768)
DCRC.write_reg(0x440, 0)
pass
#print(DCRC.DCRC.recv(32768).decode())
time.sleep(0.4)
scope.setup_AWG((charge_pulse)* 100 * 32768, shots=9)
scope.trigger_AWG()
DCRC.reset_ADC()
time.sleep(0.5)
thpulse = DCRC.readout(qchan, 40*4096, offset=4096) #16384
PlotPulse([thpulse], "Test Charge Pulse", plabels=['Q'+str(qchan-12)])
pass
LC_coeffs = zeros((4,16), 'i8')
LC_coeffs[0,qchan] = 127 # only one channel
raw_FIR_coeffs = zeros((4, 1024))
raw_FIR_coeffs[0, 0:10] = 3 # 10 baseline samples
raw_FIR_coeffs[0, 10:13] = -10 # 3 signal samples
FIR_coeffs = asarray(raw_FIR_coeffs * 3276, 'i8')
trig = trig_sim.Trigger(bits_phonon=16, bits_charge=16,
phonon_DF_R=16, phonon_DF_N=3, phonon_DF_M=1, phonon_start=0,
charge_DF_R=64, charge_DF_N=3, charge_DF_M=1, charge_start=0,
LC_coeffs=LC_coeffs, LC_bits_out=46,
LC_bits_coeff=8, LC_discard_MSBs=[0,0,0,0],
FIR_coeffs=FIR_coeffs, FIR_bits_out=32,
FIR_bits_coeff=16, FIR_discard_MSBs=[0,0,0,0],
ThL_selectors=array([0,1,1,1,1,1,1,1], dtype='uint'),
ThL_activation_thresholds = 32767*ones(8, int),
ThL_deactivation_thresholds = zeros(8, int),
PS_max_window_lengths=(2**31 - 1)*ones(4, dtype='uint'),
PS_saturated_pulse_offsets=zeros(4, dtype='uint'),
TrL_selectors=array([0,1,1,1,1,1,1,1], dtype='uint'),
TrL_enables=array([1,0,0,0,0,0,0,0], dtype=bool),
TrL_requires=zeros((8,16), bool), TrL_vetos=zeros((8, 16), bool),
TrL_prescales=ones(8, dtype='float'))
trig.ThL.ThLs[0].set_thresholds(500, 0)
tc = trig_controls.Trig_Controls(DCRC, trig, verbose=False)
def get_atleast1_trig():
trigs = array([])
trys = 0
while len(trigs) == 0:
if trys >= 10:
raise RuntimeError("Tried %d times, but recorded no triggers"%trys)
DCRC.clear_trig_FIFO()
scope.trigger_AWG()
time.sleep(0.25)
trigs = DCRC.read_trig_FIFO()
trys += 1
return trigs
def readout_trig(one_trigger):
downsample_offset = (one_trigger['timestamp']-7) % 16 + 7
dat = ([asarray(DCRC.readout(i, 16384, offset=one_trigger['timestamp'] - 8192 - downsample_offset), 'i8')
for i in range(12)]+
[asarray(DCRC.readout(i, 65536, offset=one_trigger['timestamp'] - 8192 - downsample_offset), 'i8')
for i in range(12,16)])
# dat.extend([zeros(4*16384, 'i8')]*4)
trig.reset()
trig.through_FIR.send(dat)
FIRdat = trig.through_FIR.send(dat)
return dat, FIRdat
#scope.setup_AWG(charge_pulse * 32000, shots=1)
DCRC.reset_ADC()
#DCRC.write_reg(0x0, 0x1)
# Configure the trigger for non-inverted pulses
trig.set_FIR_coeffs(FIR_coeffs)
tc.configure_trigger()
time.sleep(0.75)
trigs = get_atleast1_trig()
dat, FIRdat = readout_trig(trigs[0])
#assert amax(FIRdat[0]) == trigs[0]['amplitude']
PlotPulse([dat[qchan]], plttitle='Triggered charge pulse')
show()
close()
PlotPulse([FIRdat[0]], plttitle='FIR output')
show()
close()
qtrig_pulses = zeros((4,16384*4), '>i2')
qtrigFIR_pulses = zeros((4,1024), '>i2')
LC_coeffs = zeros((4, 16), 'i8')
LC_coeffs[0, 12] = 127
trig.set_LC_coeffs(LC_coeffs)
tc.configure_trigger()
time.sleep(0.25)
#qchs=[12,14,15,13]
#qchs=[12,13,14,15]
qchs=[12,13,14,15]
register=[0,3,2,1]
reg_qchs=[12,15,14,13]
#minibob=[3,2,1,0]
minibob=[3,2,1,0]
for i in range(len(qchs)):
LC_coeffs = zeros((4, 16), 'i8')
LC_coeffs[0, qchs[i]] = 127
trig.set_LC_coeffs(LC_coeffs)
tc.configure_trigger()
time.sleep(0.25)
keepgoing = input("Is the signal input connected to Q{}, and already triggering? (y/n)".format(minibob[i]))
if keepgoing.strip() not in ['y', 'yes']: break
try:
trigs = get_atleast1_trig()
except:
flag=1
continue
datatrigs = trigs[(trigs['trigword']!=0)&(trigs['trigbits']!=255)]
dat, FIRdat = readout_trig(datatrigs[0])
assert amax(FIRdat[0]) == datatrigs[0]['amplitude']
#dat, FIRdat = readout_trig(trigs[0])
#assert amax(FIRdat[0]) == trigs[0]['amplitude']
qtrig_pulses[i] = dat[qchs[i]]
qtrigFIR_pulses[i] = FIRdat[0]
if flag==1:
flag=0
print("Channel {} is not triggered".format(tchan))
qtrig_tabs = widgets.Tab()
display(qtrig_tabs)
qtrig_tabs.children = [widgets.Output() for ii in range(len(qchs))]
for j,qchan in enumerate(qchs):
qtrig_tabs.set_title(j, "qCh.%d"%qchan)
with qtrig_tabs.children[j]:
PlotPulse(qtrig_pulses[j], plttitle="Triggered Input Pulse, Charge Channel {}".format(qchan))
show()
close()
PlotPulse(qtrigFIR_pulses[j], plttitle="FIR Output, Charge Channel {}".format(qchan))
show()
close()