#include "ApfelTest.h" #include "ApfelGui.h" #include "ApfelSetup.h" #include #include "errno.h" #include #include ApfelTest::ApfelTest () : fOwner (0), fCurrentSetup (0), fTestLength (0), fCurrentGain(0), fMultiPulserMode(false) { fReferenceValues[1]=ApfelTestResults(); fReferenceValues[16]=ApfelTestResults(); fReferenceValues[32]=ApfelTestResults(); InitReferenceValues(); ResetSequencerList(); } void ApfelTest::InitReferenceValues(bool invertedslope) { fReferenceValues[1].Reset(invertedslope); // gain 1 is always opposite slope of high gains // gain 1, dac2 //559 2790 575 2833 591 2823 607 2835 623 2873 639 2826 655 2804 671 3381 687 4459 703 5547 719 9407 735 7824 751 8950 767 10102 783 10493 799 12311 815 13345 831 14311 847 14970 863 15215 879 15231 895 15243 911 15247 927 15258 int valDAC_1[APFEL_DAC_CURVEPOINTS]= {559, 575, 591, 607, 623, 639, 655, 671, 687, 703, 719, 735, 751, 767, 783, 799, 815, 831, 847, 863, 879, 895, 911, 927}; int valADC_1[APFEL_DAC_CURVEPOINTS]= {2790, 2833, 2823, 2835, 2873, 2826, 2804, 3381,4459, 5547, 6407, 7824, 8950, 10102, 10493, 12311, 13345, 14311, 14970, 15215, 15231,15243,15247,15258 }; for(int i=0; iAccessTestResults (fCurrentGain, apfel); theResults.Begin (); // make sure that we do not mix up results from 2 different runs! // additionally, we save here the appropriate envrionment descriptors: theResults.SetAddressId(fCurrentSetup->GetApfelID(apfel)); // copy here the most recent current scan tests theResults.SetCurrentASIC(fCurrentSetup->GetCurrentASIC(apfel)); theResults.SetCurrentHV(fCurrentSetup->GetCurrentHV(apfel)); theResults.SetCurrentDiode(fCurrentSetup->GetCurrentDiode(apfel)); // copy here the most recent addressing scan tests if done before sequencer theResults.SetIDScan(fCurrentSetup->IsIDScanOK(apfel)); theResults.SetGeneralCallScan(fCurrentSetup->IsGeneralScanOK(apfel)); theResults.SetReverseIDScan(fCurrentSetup->IsReverseIDScanOK(apfel)); theResults.SetRegisterScan(fCurrentSetup->IsRegisterScanOK(apfel)); // qr tag for single chip: QString descriptor; fCurrentSetup->GetChipID(apfel, descriptor); theResults.SetChipDescriptor(descriptor); // qr tag for carrier board: theResults.SetCarrierBoardDescriptor(fCurrentSetup->GetBoardID()); // environment temperature as logged by the user: theResults.SetTemperatureInfo(fCurrentSetup->GetTemperature()); printm ("Recorded Slot %d, Chip id %s ", apfel, descriptor.toLatin1 ().constData ()); } // apfel } break; case SEQ_FINALIZE: { int apfel=0, dac=0; fCurrentSetup->EvaluateDACIndices(febexchannel,apfel,dac); for (int apfel = 0; apfel < APFEL_NUMCHIPS; ++apfel) { ApfelTestResults& theResults=fCurrentSetup->AccessTestResults(fCurrentGain, apfel); // after the gain measurements, we have to copy the results of the general tests to structure for the very gain theResults.SetIDScan(fCurrentSetup->IsIDScanOK(apfel)); theResults.SetGeneralCallScan(fCurrentSetup->IsGeneralScanOK(apfel)); theResults.SetReverseIDScan(fCurrentSetup->IsReverseIDScanOK(apfel)); theResults.SetRegisterScan(fCurrentSetup->IsRegisterScanOK(apfel)); theResults.SetCurrentASIC(fCurrentSetup->GetCurrentASIC(apfel)); theResults.SetCurrentHV(fCurrentSetup->GetCurrentHV(apfel)); theResults.SetCurrentDiode(fCurrentSetup->GetCurrentDiode(apfel)); theResults.Finish(); } printm("Test for gain %d has finished.",fCurrentGain); } break; case SEQ_GAIN_1: printm("ApfelTest Sets to gain 1."); // always keep setup consistent with the applied values: fCurrentSetup->SetHighGain(false); // apply gain 1 by this. fOwner->SetSwitches(fCurrentSetup->IsApfelInUse(), fCurrentSetup->IsHighGain(), fCurrentSetup->IsStretcherInUse()); fCurrentGain=1; break; case SEQ_GAIN_16: printm("ApfelTest Sets to gain 16."); // always keep setup consistent with the applied values: fCurrentSetup->SetHighGain(true); // apply gain 1 by this. fOwner->SetSwitches(fCurrentSetup->IsApfelInUse(), fCurrentSetup->IsHighGain(), fCurrentSetup->IsStretcherInUse()); for(int apfel=0; apfelSetLowGain (apfel, channel, true); fOwner->SetGain(apfel, channel, true); } } fCurrentGain=16; break; case SEQ_GAIN_32: printm("ApfelTest Sets to gain 32."); // always keep setup consistent with the applied values: fCurrentSetup->SetHighGain(true); // apply gain 1 by this. // note that we do not change other switches for the moment. fOwner->SetSwitches(fCurrentSetup->IsApfelInUse(), fCurrentSetup->IsHighGain(), fCurrentSetup->IsStretcherInUse()); // now need to change channel gains: for(int apfel=0; apfelSetLowGain (apfel, channel, false); fOwner->SetGain(apfel, channel, false); } } fCurrentGain=32; break; case SEQ_AUTOCALIB: printm("ApfelTest is doing DAC Autocalibration."); fOwner->AutoCalibrate_all(); // now save DAC settings to structure: for(int apfel=0; apfelAccessTestResults(fCurrentGain, apfel); for(int dac=0; dacGetDACValue(apfel,dac)); } } break; case SEQ_NOISESAMPLE: printm("ApfelTest is measuring ADC trace samples of channel %d",febexchannel); { int apfel=0, dac=0; fCurrentSetup->EvaluateDACIndices(febexchannel,apfel,dac); fOwner->PulseTimer_changed (0); // switch off manual pulser timer during benchmark! // set baseline to standard values and define polarities: int polarityflag=-1; if(fCurrentGain==1) { fOwner->AutoAdjustChannel(febexchannel, 12000); // negative peaks, high baseline polarityflag=0; fOwner->SetPeakfinderPolarityNegative(true); // TODO 2016: check slope setup here? if(IsMultiPulserMode()) fCurrentSetup->SetTestPulsePostive (apfel, true); // for pandatestboard we send positive pulses anyway, but get negative peaks } else { fOwner->AutoAdjustChannel(febexchannel, 4000); // positive peaks polarityflag=1; fOwner->SetPeakfinderPolarityNegative(false); if(IsMultiPulserMode()) fCurrentSetup->SetTestPulsePostive (apfel, true); } // before getting the sample, we invoke the pulser for this channel: int peakPositions[APFELTEST_MULTIPULSER_PEAKS]; // remember the peaks found after each pulser in multi pulser mode int peakAmplitudes[APFELTEST_MULTIPULSER_PEAKS]; if(IsMultiPulserMode()) { fCurrentSetup->SetTestPulseEnable (apfel, 0, true); // need both channels of apfel to trigger with mbs fCurrentSetup->SetTestPulseEnable (apfel, 1, true); uint8_t amplitude[APFELTEST_MULTIPULSER_PEAKS]; switch(fCurrentGain) { case 1: amplitude[0]=9; amplitude[1]=12; amplitude[2]=15; break; case 16: amplitude[0]=2; amplitude[1]=3; amplitude[2]=4; break; case 32: default: amplitude[0]=1; amplitude[1]=2; amplitude[2]=3; break; }; for (int numpuls = 0; numpuls < APFELTEST_MULTIPULSER_PEAKS; ++numpuls) { fCurrentSetup->SetTestPulseAmplitude (apfel, 0, amplitude[numpuls]); fCurrentSetup->SetTestPulseAmplitude (apfel, 1, amplitude[numpuls]); for (int t = 0; t < 5; ++t) // TODO: configurable number of pulses? { fOwner->SetPulser (apfel); // invoke a single pulse of specified setup //usleep(50); // wait for mbs trigger } usleep(200); // wait for mbs trigger fOwner->AcquireSample (febexchannel,polarityflag); // this includes peak finder for MBS case // need pulseindex here? fOwner->ShowSample(febexchannel,true); peakAmplitudes[numpuls] = fCurrentSetup->GetSamplePeakHeight (febexchannel, 0); // remember highest peak peakPositions[numpuls] = fCurrentSetup->GetSamplePeakPosition (febexchannel, 0); } // numpuls } // multipulsermode else { // use external pulser fOwner->AcquireSample(febexchannel, polarityflag); // this includes peak finder for MBS case fOwner->ShowSample(febexchannel,true); } // note that this works only in mbs mode due to the trigger that we still not have for adc buffer // in any case we only show last sample and take baselines from it: //fOwner->ShowSample(febexchannel,true); double mean=fCurrentSetup->GetADCMean(febexchannel); double sigma=fCurrentSetup->GetADCSigma(febexchannel); double minimum=fCurrentSetup->GetADCMiminum(febexchannel); double maximum=fCurrentSetup->GetADCMaximum(febexchannel); int baselinelow=fCurrentSetup->GetADCBaslineLowerBound(febexchannel); int baselineup=fCurrentSetup->GetADCBaslineUpperBound(febexchannel); ApfelTestResults& theResults=fCurrentSetup->AccessTestResults(fCurrentGain, apfel); // kludge to get also results from second adc for dac3: we record it if(fCurrentGain==1) { if((febexchannel%2)!=0) { dac++; printm("\tChannel %d sample for gain 1: -shifted dac to index %d to record results",febexchannel, dac); } } theResults.SetAdcSampleMean(dac,mean); theResults.SetAdcSampleSigma(dac,sigma); theResults.SetAdcSampleMinimum(dac,minimum); theResults.SetAdcSampleMinimum(dac,maximum); theResults.SetAdcBaselineLowerBound(dac, baselinelow); theResults.SetAdcBaselineUpperBound(dac, baselineup); printm("\tChannel %d : baseline-(%d...%d), mean=%f sigma=%f minimum=%f maximum=%f",febexchannel, baselinelow, baselineup, mean,sigma,minimum,maximum); // insert here the found peak position into the test results: theResults.ResetAdcPeaks(dac); bool peaksnegative=fCurrentSetup->IsSamplePeaksNegative(febexchannel); theResults.SetNegativeAdcPeaks(dac,peaksnegative); if(IsMultiPulserMode()) { printm("\t\tfound %d peaks (polarity:%s) from different pulses", APFELTEST_MULTIPULSER_PEAKS, (peaksnegative ? "negative":"positive")); // internal pulser: take the highest peaks found of 3 samples for (int i = 0; i < APFELTEST_MULTIPULSER_PEAKS; ++i) { theResults.AddAdcPeak(dac, peakPositions[i], peakAmplitudes[i]); } } else { // external pulser: just take the first n peaks of a single sample int numpeaks = fCurrentSetup->NumSamplePeaks (febexchannel); printm("\t\tfound %d peaks (polarity:%s) ", numpeaks, (peaksnegative ? "negative":"positive")); for (int i = 0; i < APFEL_ADC_NUMMAXIMA; ++i) { uint16_t height = 0; int pos = 0; if (i < numpeaks) { height = fCurrentSetup->GetSamplePeakHeight (febexchannel, i); pos = fCurrentSetup->GetSamplePeakPosition (febexchannel, i); printm("\t\t (pos:%d,ADC;%d)",pos,height); theResults.AddAdcPeak(dac,pos, height); } } } } break; case SEQ_BASELINE: printm("Benchmark Timer is doing baseline calibration of channel %d", febexchannel); { fOwner->CalibrateADC(febexchannel); int apfel=0, dac=0; fCurrentSetup->EvaluateDACIndices(febexchannel,apfel,dac); ApfelTestResults& theResults=fCurrentSetup->AccessTestResults(fCurrentGain, apfel); GainSetup gainSetup=fCurrentSetup->AccessGainSetup(fCurrentGain,febexchannel); // kludge to get also results from second adc for dac3: we record it for dac4 if (fCurrentGain == 1) { if ((febexchannel % 2) != 0) { dac++; printm ("\tChannel %d baseline for gain 1: -shifted dac to index %d to record results", febexchannel, dac); } } // will not work here, since result has only gain curve for channel, not for dac theResults.SetGainParameter(dac, gainSetup); } break; case SEQ_CURVE: printm("Benchmark Timer is evaluating DAC curve of channel %d", febexchannel); fOwner->ScanDACCurve(fCurrentGain, febexchannel); break; case SEQ_ADDRESS_SCAN: { int apfel=febexchannel; // note that we misuse febexchannel parameter here to work on specific apfelchip. todo: change paramter name printm("Benchmark Timer is evaluating address scan for apfel chip %d", apfel); fOwner->ExecuteIDScanTest(febexchannel); } break; case SEQ_CURRENT_MEASUEREMENT: { int apfel=febexchannel; // note that we misuse febexchannel parameter here to work on specific apfelchip. todo: change paramter name printm("Benchmark Timer is evaluating current measurement scan for apfel ch ip %d", apfel); fOwner->ExecuteCurrentScan(apfel); } break; default: printm("Benchmark Timer will NOT execute unknown command %d for channel %d",com.GetAction(), com.GetChannel()); return false; break; }; return true; }