diff --git a/lab4_controller.py b/lab4_controller.py index bd5dcc8..e17b38f 100644 --- a/lab4_controller.py +++ b/lab4_controller.py @@ -199,9 +199,13 @@ def automatch_phab(self, lab, match=1): phab = self.scan_value(scanNum, wr_edge) & 0x01 if self.invertSync: phab = phab ^ 0x01 - + loop_count=0 while phab != match: print("LAB%d wrong PHAB phase, resetting." % i) + loop_count=loop_count+1 + if loop_count>9: + err=True + break self.clr_phase(i) phab = self.scan_value(scanNum, wr_edge) & 0x01 if self.invertSync: diff --git a/radcalib.py b/radcalib.py index 1eb8bf7..1b4b083 100644 --- a/radcalib.py +++ b/radcalib.py @@ -108,28 +108,89 @@ def updatePedestals(self): self.calib['pedestals'] = rawped.reshape(24, 4096) print("Update complete") - # assumes *nothing* other than the LAB4's been defaulted and testpatern mode is off - # The initial tune finds the trim feedback and shifts all the trims to ensure - # the slow sample is tunable - def initialTune(self, lab, maxTries=50, freq=510, tryReg3ForFailedDLL=True, verbose=False,bad_LAB=False): + def get_tune_params(self): + #if sampling rate ==2400 + seam_slow_factor=1.03 #1.03 + seam_fast_factor=0.97 #0.97 - # Start off by dead-reckoning the initial target - # Start off by trying to use the DLL. - if self.calib['specifics'][lab][2] == 1024: - print("Defaults say to NOT use the DLL.") - seamTuneNum = 3 + slow_slow_factor=1.03 #1.01 + slow_fast_factor=0.97 #0.95 + + mean_slow_factor=1.0005 #0.1% of 416.66 means this ends when the mean is ~0.4ps off of ideal. seam sample should close enough then. + mean_fast_factor=0.999 + + if(self.dev.SAMPLING_RATE==3200): #help tuning a bit + seam_slow_factor=1.06 + seam_fast_factor=0.94 + + slow_slow_factor=1.03 + slow_fast_factor=0.93 #confusing IK but it's slow sample. make is slightly fast + + mean_slow_factor=1.003 #0.1% of 416.66 means this ends when the mean is ~0.4ps off of ideal. seam sample should close enough then. + mean_fast_factor=0.997 + + return seam_slow_factor,seam_fast_factor,slow_slow_factor,slow_fast_factor,mean_slow_factor,mean_fast_factor + + def adjust_seam(self,lab,seamTuneNum,seamSample,mode='seam'): + seamTuneNum=int(seamTuneNum) + # Build the delta. This is totally hacked together. + # Decrease if too fast, increase if too slow. + # Change by 3 if it's within 50, change by 7 if it's between 50-100, + # change by 15 otherwise. Convergence here is slow, but we're trying to + # avoid bouncing, and we're also trying to avoid the negative case. + diff = np.abs(seamSample - self.nomSample) + s_diff=seamSample-self.nomSample + if seamTuneNum == 3: + delta= 1 else: - print("Defaults say to use the DLL.") - seamTuneNum = 11 - + delta = 1 #was 3, takes longer but oh well. better granularity when we're close + #seam tuning + if mode == 'seam' and diff > 50: + delta += random.randint(1,3) #randomness back in + if mode =='seam' and diff > 100: + delta += random.randint(2,6) #max step size of 10. don't want to jump past optimal point too much + + #mean tuning. diff is sizably different from the seam diff + if mode=='mean' and diff > 0.3: + delta += 3 + if mode=='mean' and diff > 0.6: + delta += 6 + + #switch signs of delta if using VadjN or if we need to change directions + if seamTuneNum ==3: + delta = -1*delta + if mode=='seam' and s_diff<0: + delta=-1*delta + if mode=='mean' and s_diff>0: + delta=-1*delta + + cur = self.calib['specifics'][lab][seamTuneNum] + newVal = cur+delta; + #if newVal < (self.nomSample*1.28): + # print("hmm feedback got to small. let's try something random!") + # newVal = random.randrange(800,1200) + # time.sleep(2); + print("Seam sample: Feedback LAB%d (%f): %d -> %d (register %d)" % (lab, seamSample, cur, newVal, seamTuneNum)) + self.calib['specifics'][lab][seamTuneNum] = newVal + + def adjust_slow(self,slowSample,lab,slow_slow_factor,slow_fast_factor,slow_step): + if slowSample> (self.nomSample*slow_slow_factor): + slow_step=np.abs(slow_step) + print('need to speed up slow sample') + elif slowSample<(self.nomSample*slow_fast_factor): + slow_step=-slow_step + print('need to slow down slow sample') + oldavg = 0 + for i in range(257, 383): + old = self.calib['specifics'][lab][i] + oldavg += old + self.calib['specifics'][lab][i] = old + slow_step + oldavg = oldavg/126 + print("Slow sample: LAB%d (%f): %d -> %d" % (lab, slowSample, oldavg, oldavg + slow_step)) + oldavg = oldavg + slow_step - initialState = self.calib['specifics'][lab] - self.dev.labc.update(lab) # make sure we are using the initial state - #balance sstin/sstout widths - self.calib['specifics'][lab][8]=self.dev.labc.autotune_vadjp(lab,initial=self.calib['specifics'][lab][8]) #this guy can break things but might be useful to keep - self.dev.labc.update(lab) # make sure we are using the initial state - + def find_sspin(self,lab,maxTries,tryReg3ForFailedDLL,initialState): self.dev.monSelect(lab) self.dev.labc.set_tmon(lab, self.dev.labc.tmon['SSPin']) # SSPin is *supposed* to be around 600 samples long in an ideal world, @@ -162,6 +223,7 @@ def initialTune(self, lab, maxTries=50, freq=510, tryReg3ForFailedDLL=True, ver seamTuneNum =3 maxTries*=3 print("Switching to VadjN") + while width > 1300 and curTry < maxTries: #below 1000 for 3.2GHz, maybe 1000*1.33=1300 for 2.4GHz newAvg = 0 print('raising avg sample trim by 25') @@ -181,6 +243,30 @@ def initialTune(self, lab, maxTries=50, freq=510, tryReg3ForFailedDLL=True, ver self.calib['specifics'][lab] = initialState self.dev.labc.update(lab) return False + return curTry + # assumes *nothing* other than the LAB4's been defaulted and testpatern mode is off + # The initial tune finds the trim feedback and shifts all the trims to ensure + # the slow sample is tunable + + def initialTune(self, lab, maxTries=50, freq=510, tryReg3ForFailedDLL=True, verbose=False,bad_LAB=False): + + # Start off by dead-reckoning the initial target + # Start off by trying to use the DLL. + if self.calib['specifics'][lab][2] == 1024: + print("Defaults say to NOT use the DLL.") + seamTuneNum = 3 + else: + print("Defaults say to use the DLL.") + seamTuneNum = 11 + + + initialState = self.calib['specifics'][lab] + self.dev.labc.update(lab) # make sure we are using the initial state + #balance sstin/sstout widths + self.calib['specifics'][lab][8]=self.dev.labc.autotune_vadjp(lab,initial=self.calib['specifics'][lab][8]) #this guy can break things but might be useful to keep + self.dev.labc.update(lab) # make sure we are using the initial state + + curTry=self.find_sspin(lab,maxTries,tryReg3ForFailedDLL,initialState) # Put its quad into calibration mode self.dev.calSelect(int(lab/4)) self.dev.radsig.enable(False) @@ -222,92 +308,16 @@ def initialTune(self, lab, maxTries=50, freq=510, tryReg3ForFailedDLL=True, ver do_quit=False # No idea if this second condition (oldavg < 2400) will work with different sampling rates!! # I doubt it!! - seam_slow_factor=1.03 - seam_fast_factor=0.97 - - slow_slow_factor=1.01 - slow_fast_factor=0.95 #confusing IK but it's slow sample. make is slightly fast - - mean_slow_factor=1.0005 #0.1% of 416.66 means this ends when the mean is ~0.4ps off of ideal. seam sample should close enough then. - mean_fast_factor=0.999 - - if(self.dev.SAMPLING_RATE==3200): #help tuning a bit - seam_slow_factor=1.06 - seam_fast_factor=0.94 - - slow_slow_factor=1.03 - slow_fast_factor=0.93 #confusing IK but it's slow sample. make is slightly fast - - mean_slow_factor=1.003 #0.1% of 416.66 means this ends when the mean is ~0.4ps off of ideal. seam sample should close enough then. - mean_fast_factor=0.997 + seam_slow_factor,seam_fast_factor,slow_slow_factor,slow_fast_factor,mean_slow_factor,mean_fast_factor=self.get_tune_params() slow_step=10 #was 25 - - def adjust_seam(seamSample,mode='seam'): - # Build the delta. This is totally hacked together. - # Decrease if too fast, increase if too slow. - # Change by 3 if it's within 50, change by 7 if it's between 50-100, - # change by 15 otherwise. Convergence here is slow, but we're trying to - # avoid bouncing, and we're also trying to avoid the negative case. - diff = np.abs(seamSample - self.nomSample) - s_diff=seamSample-self.nomSample - if seamTuneNum == 3: - delta= 1 - else: - delta = 1 #was 3, takes longer but oh well. better granularity when we're close - #seam tuning - if mode == 'seam' and diff > 50: - delta += random.randint(1,3) #randomness back in - if mode =='seam' and diff > 100: - delta += random.randint(2,6) #max step size of 10. don't want to jump past optimal point too much - - #mean tuning. diff is sizably different from the seam diff - if mode=='mean' and diff > 0.3: - delta += 3 - if mode=='mean' and diff > 0.6: - delta += 6 - - #switch signs of delta if using VadjN or if we need to change directions - if seamTuneNum ==3: - delta = -1*delta - if mode=='seam' and s_diff<0: - delta=-1*delta - if mode=='mean' and s_diff>0: - delta=-1*delta - - cur = self.calib['specifics'][lab][seamTuneNum] - newVal = cur+delta; - #if newVal < (self.nomSample*1.28): - # print("hmm feedback got to small. let's try something random!") - # newVal = random.randrange(800,1200) - # time.sleep(2); - print("Seam sample: Feedback LAB%d (%f): %d -> %d (register %d)" % (lab, seamSample, cur, newVal, seamTuneNum)) - self.calib['specifics'][lab][seamTuneNum] = newVal - - def adjust_slow(slowSample,slow_step): - if slowSample> (self.nomSample*slow_slow_factor): - slow_step=np.abs(slow_step) - print('need to speed up slow sample') - elif slowSample<(self.nomSample*slow_fast_factor): - slow_step=-slow_step - print('need to slow down slow sample') - oldavg = 0 - for i in range(257, 383): - old = self.calib['specifics'][lab][i] - oldavg += old - self.calib['specifics'][lab][i] = old + slow_step - oldavg = oldavg/126 - print("Slow sample: LAB%d (%f): %d -> %d" % (lab, slowSample, oldavg, oldavg + slow_step)) - oldavg = oldavg + slow_step - print('\nfirst find mean sample so timing is close') last_seam=seamSample - - - meanSample=np.mean(t[lab][1:126]) + + while(meanSample>self.nomSample*mean_slow_factor or meanSample(self.nomSample*slow_slow_factor) or seamSample > (self.nomSample*seam_slow_factor) or seamSample < (self.nomSample*seam_fast_factor): + while count<5 or rolling_slow < (self.nomSample*slow_fast_factor) or rolling_slow>(self.nomSample*slow_slow_factor) or rolling_seam > (self.nomSample*seam_slow_factor) or rolling_seam < (self.nomSample*seam_fast_factor): if curTry >= maxTries: print("HIT MAX TRIES! Initial tune failed! Restoring initial state.") self.calib['specifics'][lab] = initialState self.dev.labc.update(lab) return False - #wouldn't actually get in here if we set the contraints well enough in the loop - #if slowSample<(self.nomSample*slow_factor) and slowSample>(self.nomSample*0.95) and seamSample>(self.nomSample*0.95) and seamSample < (self.nomSample*1.05): - # print('!!!!samples very close!!!!') - # do_quit=True - - #if diff(seam)>diff(slow) do seam? - #else slow>seam do slow. - # Fix the seam if it's gone off too much. - elif (seamSample < (self.nomSample*seam_fast_factor) or seamSample > (self.nomSample*seam_slow_factor)) and bouncing<3: + + if (rolling_seam < (self.nomSample*seam_fast_factor) or rolling_seam > (self.nomSample*seam_slow_factor)) and bouncing<3: print('----------- SEAM off ----------') - adjust_seam(seamSample,mode=tune_mode) + self.adjust_seam(lab,seamTuneNum,seamSample,mode=tune_mode) if last_seam>(self.nomSample*seam_slow_factor) and seamSample<(self.nomSample*seam_fast_factor): bouncing+=1 - + elif last_seam<(self.nomSample*seam_fast_factor) and seamSample>(self.nomSample*seam_slow_factor): bouncing+=1 last_seam=seamSample if bouncing>3: print("bouncing") - - # oldelif slowSample > (self.nomSample*0.928) and oldavg <2400: - # oldelif slowSample > (self.nomSample*0.98) and oldavg <2400: - elif slowSample > (self.nomSample*slow_slow_factor) or slowSample < (self.nomSample*slow_fast_factor): + elif ((rolling_slow > (self.nomSample*slow_slow_factor) or rolling_slow < (self.nomSample*slow_fast_factor))): print('----------- SLOW off ----------') - - # We ONLY DO THIS if the seam sample's close. - # This is because the slow sample changes with the seam timing like - # everything else (actually a little more) - # - # So now, we're trying to find a *global* starting point where - # the slow sample is *too fast*. Because slowing it down is easy! - # So to do that, we slow everyone else down. Doing that means the - # the DLL portion speeds up, so the slow sample speeds up as well. - # This slows down trims 1->126 by adding 25 to them. - # Remember trim 127 is the slow sample, and trim 0 is the multichannel clock alignment trim. - - # Trim updating is a pain, sigh. - adjust_slow(slowSample,slow_step) + + self.adjust_slow(slowSample,lab,slow_slow_factor,slow_fast_factor,slow_step) bouncing=0 - #old elif slowSample < (self.nomSample*0.8) and oldavg >1800: - #old elif slowSample < (self.nomSample*0.9) and oldavg >1800: + elif False and num_outside>5: + print('---------- SPREAD off ---------') + bigs=np.argsort(np.abs(rolling_samples-self.nomSample)) + largest1=bigs[128-1:128:1] + print('working on these ',largest1,rolling_samples[largest5]) + for sample in largest1: + reg=sample+sam_2_reg + if rolling_samples[sample]>self.nomSample: + self.calib['specifics'][lab][reg]=self.calib['specifics'][lab][reg]-10 + elif rolling_samples[sample]1800: + #old elif slowSample < (self.nomSample*0.9) and oldavg >1800: + doadd=False + dopop=False + if count<=5: + doadd=True + if count>5: + dopop=True + + for i in range(128): + if doadd:rolling_means[i].append(t[lab][i]) + if dopop: + rolling_means[i].pop(0) + rolling_means[i].append(t[lab][i]) + rolling_samples=np.mean(rolling_means,axis=1) + rolling_spread=np.std(rolling_samples) + num_outside=len(np.where(rolling_samples>self.nomSample*1.02)[0]) + len(np.where(rolling_samples (self.nomSample*127.68): print("Feedback LAB%d way off (%f): %d -> %d" % (lab, (self.nomSample*128)-np.sum(t[lab][1:128]), t[lab][0], -1*t[lab][0])) t[lab][0] = -1*t[lab][0] seamSample=t[lab][0] + rolling_seam=np.mean(rolling_means[0]) + rolling_slow=np.mean(rolling_means[127]) #seamSample = np.mean(t[lab][1:127]) #make it the middle samples bc reasons slowSample = t[lab][127] + #spread=np.std(t[lab][1:127]) + print(f"rolling seam {rolling_seam:0.2f}, rolling slow {rolling_slow:0.2f}, rolling spread {rolling_spread:0.2f}") if tune_mode=='mean': seamSample=np.mean(t[lab][1:127]) #trick it again :) curTry = curTry + 1 + count=count+1 if do_quit: print('') break @@ -428,7 +465,7 @@ def adjust_slow(slowSample,slow_step): #tighter around the ideal sample time. Assuming if I push the slow fast and the fast slow #it shouldn't mess with the overall timing too much def tune_samples(self,lab,freq=510,verbose=False): - pass + print('\nTrying to tune individual samples') initialState = self.calib['specifics'][lab] self.dev.labc.update(lab) # make sure we are using the initial state @@ -474,8 +511,10 @@ def tune_samples(self,lab,freq=510,verbose=False): print('sample time %0.2f'%t[lab][slowest_sample]) exit() ''' - samples=np.arange(1,127,1) - while(spread>spread_success_range or any_bigger>10): + samples=np.arange(0,128,1) + biggest=np.argmax(t[lab][:]) + #while(spread>spread_success_range or any_bigger>10): + while(True): print('\n',tries) if tries>50: print('too long') @@ -485,23 +524,28 @@ def tune_samples(self,lab,freq=510,verbose=False): #adjust labs here for sample in samples: + if sample!=biggest: continue reg=sample+sam_2_reg + print(self.calib['specifics'][lab][reg]) if t[lab][sample]>self.nomSample+10: - self.calib['specifics'][lab][reg]=self.calib['specifics'][lab][reg]-3 + print('speed up') + self.calib['specifics'][lab][reg]=self.calib['specifics'][lab][reg]-10 elif t[lab][sample]10)[0]) print('mean and std',mean_sample,spread) - print(any_bigger,' samples outside range') + #print(any_bigger,' samples outside range') tries=tries+1 @@ -616,3 +660,4 @@ def getTimeRun(self, frequency, verbose=True): timeByWindow.transpose()[0] /= rescale # and we're done return timeByWindow +