forked from sPHENIX-Collaboration/drs4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDRS.h
executable file
·950 lines (862 loc) · 39 KB
/
DRS.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
/********************************************************************
DRS.h, S.Ritt, M. Schneebeli - PSI
$Id: DRS.h 21309 2014-04-11 14:51:29Z ritt $
********************************************************************/
#ifndef DRS_H
#define DRS_H
#include <stdio.h>
#include <string.h>
#include "averager.h"
#ifdef HAVE_LIBUSB
# ifndef HAVE_USB
# define HAVE_USB
# endif
#endif
#ifdef HAVE_USB
# include <musbstd.h>
#endif // HAVE_USB
#ifdef HAVE_VME
# include <mvmestd.h>
#endif // HAVE_VME
/* disable "deprecated" warning */
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
#ifndef NULL
#define NULL 0
#endif
int drs_kbhit();
unsigned int millitime();
/* transport mode */
#define TR_VME 1
#define TR_USB 2
#define TR_USB2 3
/* address types */
#ifndef T_CTRL
#define T_CTRL 1
#define T_STATUS 2
#define T_RAM 3
#define T_FIFO 4
#endif
/*---- Register addresses ------------------------------------------*/
#define REG_CTRL 0x00000 /* 32 bit control reg */
#define REG_DAC_OFS 0x00004
#define REG_DAC0 0x00004
#define REG_DAC1 0x00006
#define REG_DAC2 0x00008
#define REG_DAC3 0x0000A
#define REG_DAC4 0x0000C
#define REG_DAC5 0x0000E
#define REG_DAC6 0x00010
#define REG_DAC7 0x00012
#define REG_CHANNEL_CONFIG 0x00014 // low byte
#define REG_CONFIG 0x00014 // high byte
#define REG_CHANNEL_MODE 0x00016
#define REG_ADCCLK_PHASE 0x00016
#define REG_FREQ_SET_HI 0x00018 // DRS2
#define REG_FREQ_SET_LO 0x0001A // DRS2
#define REG_TRG_DELAY 0x00018 // DRS4
#define REG_FREQ_SET 0x0001A // DRS4
#define REG_TRIG_DELAY 0x0001C
#define REG_LMK_MSB 0x0001C // DRS4 Mezz
#define REG_CALIB_TIMING 0x0001E // DRS2
#define REG_EEPROM_PAGE_EVAL 0x0001E // DRS4 Eval
#define REG_EEPROM_PAGE_MEZZ 0x0001A // DRS4 Mezz
#define REG_TRG_CONFIG 0x0001C // DRS4 Eval4
#define REG_LMK_LSB 0x0001E // DRS4 Mezz
#define REG_WARMUP 0x00020 // DRS4 Mezz
#define REG_COOLDOWN 0x00022 // DRS4 Mezz
#define REG_READ_POINTER 0x00026 // DRS4 Mezz
#define REG_MAGIC 0x00000
#define REG_BOARD_TYPE 0x00002
#define REG_STATUS 0x00004
#define REG_RDAC_OFS 0x0000E
#define REG_RDAC0 0x00008
#define REG_STOP_CELL0 0x00008
#define REG_RDAC1 0x0000A
#define REG_STOP_CELL1 0x0000A
#define REG_RDAC2 0x0000C
#define REG_STOP_CELL2 0x0000C
#define REG_RDAC3 0x0000E
#define REG_STOP_CELL3 0x0000E
#define REG_RDAC4 0x00000
#define REG_RDAC5 0x00002
#define REG_STOP_WSR0 0x00010
#define REG_STOP_WSR1 0x00011
#define REG_STOP_WSR2 0x00012
#define REG_STOP_WSR3 0x00013
#define REG_RDAC6 0x00014
#define REG_RDAC7 0x00016
#define REG_EVENTS_IN_FIFO 0x00018
#define REG_EVENT_COUNT 0x0001A
#define REG_FREQ1 0x0001C
#define REG_FREQ2 0x0001E
#define REG_WRITE_POINTER 0x0001E
#define REG_TEMPERATURE 0x00020
#define REG_TRIGGER_BUS 0x00022
#define REG_SERIAL_BOARD 0x00024
#define REG_VERSION_FW 0x00026
#define REG_SCALER0 0x00028
#define REG_SCALER1 0x0002C
#define REG_SCALER2 0x00030
#define REG_SCALER3 0x00034
#define REG_SCALER4 0x00038
#define REG_SCALER5 0x0003C
/*---- Control register bit definitions ----------------------------*/
#define BIT_START_TRIG (1<<0) // write a "1" to start domino wave
#define BIT_REINIT_TRIG (1<<1) // write a "1" to stop & reset DRS
#define BIT_SOFT_TRIG (1<<2) // write a "1" to stop and read data to RAM
#define BIT_EEPROM_WRITE_TRIG (1<<3) // write a "1" to write into serial EEPROM
#define BIT_EEPROM_READ_TRIG (1<<4) // write a "1" to read from serial EEPROM
#define BIT_MULTI_BUFFER (1<<16) // Use multi buffering when "1"
#define BIT_DMODE (1<<17) // (*DRS2*) 0: single shot, 1: circular
#define BIT_ADC_ACTIVE (1<<17) // (*DRS4*) 0: stop ADC when running, 1: ADC always clocked
#define BIT_LED (1<<18) // 1=on, 0=blink during readout
#define BIT_TCAL_EN (1<<19) // switch on (1) / off (0) for 33 MHz calib signal
#define BIT_TCAL_SOURCE (1<<20)
#define BIT_REFCLK_SOURCE (1<<20)
#define BIT_FREQ_AUTO_ADJ (1<<21) // DRS2/3
#define BIT_TRANSP_MODE (1<<21) // DRS4
#define BIT_ENABLE_TRIGGER1 (1<<22) // External LEMO/FP/TRBUS trigger
#define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz)
#define BIT_READOUT_MODE (1<<23) // (*DRS3*,*DRS4*) 0:start from first bin, 1:start from domino stop
#define BIT_DELAYED_START (1<<24) // DRS2: start domino wave 400ns after soft trigger, used for waveform
// generator startup
#define BIT_NEG_TRIGGER (1<<24) // DRS4: use high-to-low trigger if set
#define BIT_ACAL_EN (1<<25) // connect DRS to inputs (0) or to DAC6 (1)
#define BIT_TRIGGER_DELAYED (1<<26) // select delayed trigger from trigger bus
#define BIT_ADCCLK_INVERT (1<<26) // invert ADC clock
#define BIT_REFCLK_EXT (1<<26) // use external MMCX CLKIN refclk
#define BIT_DACTIVE (1<<27) // keep domino wave running during readout
#define BIT_STANDBY_MODE (1<<28) // put chip in standby mode
#define BIT_TR_SOURCE1 (1<<29) // trigger source selection bits
#define BIT_DECIMATION (1<<29) // drop all odd samples (DRS4 mezz.)
#define BIT_TR_SOURCE2 (1<<30) // trigger source selection bits
#define BIT_ENABLE_TRIGGER2 (1<<31) // analog threshold (internal) trigger
/* DRS4 configuration register bit definitions */
#define BIT_CONFIG_DMODE (1<<8) // 0: single shot, 1: circular
#define BIT_CONFIG_PLLEN (1<<9) // write a "1" to enable the internal PLL
#define BIT_CONFIG_WSRLOOP (1<<10) // write a "1" to connect WSROUT to WSRIN internally
/*---- Status register bit definitions -----------------------------*/
#define BIT_RUNNING (1<<0) // one if domino wave running or readout in progress
#define BIT_NEW_FREQ1 (1<<1) // one if new frequency measurement available
#define BIT_NEW_FREQ2 (1<<2)
#define BIT_PLL_LOCKED0 (1<<1) // 1 if PLL has locked (DRS4 evaluation board only)
#define BIT_PLL_LOCKED1 (1<<2) // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only)
#define BIT_PLL_LOCKED2 (1<<3) // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only)
#define BIT_PLL_LOCKED3 (1<<4) // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only)
#define BIT_SERIAL_BUSY (1<<5) // 1 if EEPROM operation in progress
#define BIT_LMK_LOCKED (1<<6) // 1 if PLL of LMK chip has locked (DRS4 mezzanine board only)
#define BIT_2048_MODE (1<<7) // 1 if 2048-bin mode has been soldered
enum DRSBoardConstants {
kNumberOfChannelsMax = 10,
kNumberOfCalibChannelsV3 = 10,
kNumberOfCalibChannelsV4 = 8,
kNumberOfBins = 1024,
kNumberOfChipsMax = 4,
kFrequencyCacheSize = 10,
kBSplineOrder = 4,
kPreCaliculatedBSplines = 1000,
kPreCaliculatedBSplineGroups = 5,
kNumberOfADCBins = 4096,
kBSplineXMinOffset = 20,
kMaxNumberOfClockCycles = 100,
};
enum DRSErrorCodes {
kSuccess = 0,
kInvalidTriggerSignal = -1,
kWrongChannelOrChip = -2,
kInvalidTransport = -3,
kZeroSuppression = -4,
kWaveNotAvailable = -5
};
/*---- callback class ----*/
class DRSCallback
{
public:
virtual void Progress(int value) = 0;
virtual ~DRSCallback() {};
};
/*------------------------*/
class DRSBoard;
class ResponseCalibration {
protected:
class CalibrationData {
public:
class CalibrationDataChannel {
public:
unsigned char fLimitGroup[kNumberOfBins]; //!
float fMin[kNumberOfBins]; //!
float fRange[kNumberOfBins]; //!
short fOffset[kNumberOfBins]; //!
short fGain[kNumberOfBins]; //!
unsigned short fOffsetADC[kNumberOfBins]; //!
short *fData[kNumberOfBins]; //!
unsigned char *fLookUp[kNumberOfBins]; //!
unsigned short fLookUpOffset[kNumberOfBins]; //!
unsigned char fNumberOfLookUpPoints[kNumberOfBins]; //!
float *fTempData; //!
private:
CalibrationDataChannel(const CalibrationDataChannel &c); // not implemented
CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // not implemented
public:
CalibrationDataChannel(int numberOfGridPoints)
:fTempData(new float[numberOfGridPoints]) {
int i;
for (i = 0; i < kNumberOfBins; i++) {
fData[i] = new short[numberOfGridPoints];
}
memset(fLimitGroup, 0, sizeof(fLimitGroup));
memset(fMin, 0, sizeof(fMin));
memset(fRange, 0, sizeof(fRange));
memset(fOffset, 0, sizeof(fOffset));
memset(fGain, 0, sizeof(fGain));
memset(fOffsetADC, 0, sizeof(fOffsetADC));
memset(fLookUp, 0, sizeof(fLookUp));
memset(fLookUpOffset, 0, sizeof(fLookUpOffset));
memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints));
}
~CalibrationDataChannel() {
int i;
delete fTempData;
for (i = 0; i < kNumberOfBins; i++) {
delete fData[i];
delete fLookUp[i];
}
}
};
bool fRead; //!
CalibrationDataChannel *fChannel[10]; //!
unsigned char fNumberOfGridPoints; //!
int fHasOffsetCalibration; //!
float fStartTemperature; //!
float fEndTemperature; //!
int *fBSplineOffsetLookUp[kNumberOfADCBins]; //!
float **fBSplineLookUp[kNumberOfADCBins]; //!
float fMin; //!
float fMax; //!
unsigned char fNumberOfLimitGroups; //!
static float fIntRevers[2 * kBSplineOrder - 2];
private:
CalibrationData(const CalibrationData &c); // not implemented
CalibrationData &operator=(const CalibrationData &rhs); // not implemented
public:
CalibrationData(int numberOfGridPoints);
~CalibrationData();
static int CalculateBSpline(int nGrid, float value, float *bsplines);
void PreCalculateBSpline();
void DeletePreCalculatedBSpline();
};
// General Fields
DRSBoard *fBoard;
double fPrecision;
// Fields for creating the Calibration
bool fInitialized;
bool fRecorded;
bool fFitted;
bool fOffset;
bool fCalibrationValid[2];
int fNumberOfPointsLowVolt;
int fNumberOfPoints;
int fNumberOfMode2Bins;
int fNumberOfSamples;
int fNumberOfGridPoints;
int fNumberOfXConstPoints;
int fNumberOfXConstGridPoints;
double fTriggerFrequency;
int fShowStatistics;
FILE *fCalibFile;
int fCurrentLowVoltPoint;
int fCurrentPoint;
int fCurrentSample;
int fCurrentFitChannel;
int fCurrentFitBin;
float *fResponseX[10][kNumberOfBins];
float *fResponseY;
unsigned short **fWaveFormMode3[10];
unsigned short **fWaveFormMode2[10];
short **fWaveFormOffset[10];
unsigned short **fWaveFormOffsetADC[10];
unsigned short *fSamples;
int *fSampleUsed;
float *fPntX[2];
float *fPntY[2];
float *fUValues[2];
float *fRes[kNumberOfBins];
float *fResX[kNumberOfBins];
double *fXXFit;
double *fYYFit;
double *fWWFit;
double *fYYFitRes;
double *fYYSave;
double *fXXSave;
double fGainMin;
double fGainMax;
float **fStatisticsApprox;
float **fStatisticsApproxExt;
// Fields for applying the Calibration
CalibrationData *fCalibrationData[kNumberOfChipsMax];
private:
ResponseCalibration(const ResponseCalibration &c); // not implemented
ResponseCalibration &operator=(const ResponseCalibration &rhs); // not implemented
public:
ResponseCalibration(DRSBoard* board);
~ResponseCalibration();
void SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0);
void ResetCalibration();
bool RecordCalibrationPoints(int chipNumber);
bool RecordCalibrationPointsV3(int chipNumber);
bool RecordCalibrationPointsV4(int chipNumber);
bool FitCalibrationPoints(int chipNumber);
bool FitCalibrationPointsV3(int chipNumber);
bool FitCalibrationPointsV4(int chipNumber);
bool OffsetCalibration(int chipNumber);
bool OffsetCalibrationV3(int chipNumber);
bool OffsetCalibrationV4(int chipNumber);
double GetTemperature(unsigned int chipIndex);
bool WriteCalibration(unsigned int chipIndex);
bool WriteCalibrationV3(unsigned int chipIndex);
bool WriteCalibrationV4(unsigned int chipIndex);
bool ReadCalibration(unsigned int chipIndex);
bool ReadCalibrationV3(unsigned int chipIndex);
bool ReadCalibrationV4(unsigned int chipIndex);
bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, short *uWaveform,
int triggerCell, float threshold, bool offsetCalib);
bool SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel);
bool IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; }
double GetPrecision() const { return fPrecision; };
double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; };
double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; };
double GetMeasPointXAt(int ip) const { return fXXSave[ip]; };
double GetMeasPointYAt(int ip) const { return fYYSave[ip]; };
protected:
void InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples,
int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints,
double triggerFrequency, int showStatistics);
void DeleteFields();
void CalibrationTrigger(int mode, double voltage);
void CalibrationStart(double voltage);
static float GetValue(float *coefficients, float u, int n);
static int Approx(float *p, float *uu, int np, int nu, float *coef);
static void LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt);
static int LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n);
static void Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up, float **c, int iC1,
int iC2, int ice, int ncv);
static int MakeDir(const char *path);
static void Average(int method,float *samples,int numberOfSamples,float &mean,float &error,float sigmaBoundary);
};
class DRSBoard {
protected:
class TimeData {
public:
class FrequencyData {
public:
int fFrequency;
double fBin[kNumberOfBins];
};
enum {
kMaxNumberOfFrequencies = 4000
};
int fChip;
int fNumberOfFrequencies;
FrequencyData *fFrequency[kMaxNumberOfFrequencies];
private:
TimeData(const TimeData &c); // not implemented
TimeData &operator=(const TimeData &rhs); // not implemented
public:
TimeData()
:fChip(0)
,fNumberOfFrequencies(0) {
}
~TimeData() {
int i;
for (i = 0; i < fNumberOfFrequencies; i++) {
delete fFrequency[i];
}
}
};
public:
// DAC channels (CMC Version 1 : DAC_COFSA,DAC_COFSB,DAC_DRA,DAC_DSA,DAC_TLEVEL,DAC_ACALIB,DAC_DSB,DAC_DRB)
unsigned int fDAC_COFSA;
unsigned int fDAC_COFSB;
unsigned int fDAC_DRA;
unsigned int fDAC_DSA;
unsigned int fDAC_TLEVEL;
unsigned int fDAC_ACALIB;
unsigned int fDAC_DSB;
unsigned int fDAC_DRB;
// DAC channels (CMC Version 2+3 : DAC_COFS,DAC_DSA,DAC_DSB,DAC_TLEVEL,DAC_ADCOFS,DAC_CLKOFS,DAC_ACALIB)
unsigned int fDAC_COFS;
unsigned int fDAC_ADCOFS;
unsigned int fDAC_CLKOFS;
// DAC channels (CMC Version 4 : DAC_ROFS_1,DAC_DSA,DAC_DSB,DAC_ROFS_2,DAC_ADCOFS,DAC_ACALIB,DAC_INOFS,DAC_BIAS)
unsigned int fDAC_ROFS_1;
unsigned int fDAC_ROFS_2;
unsigned int fDAC_INOFS;
unsigned int fDAC_BIAS;
// DAC channels (USB EVAL1 (fBoardType 5) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS)
// DAC channels (USB EVAL3 (fBoardType 7) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS)
unsigned int fDAC_CMOFS;
unsigned int fDAC_CALN;
unsigned int fDAC_CALP;
unsigned int fDAC_ONOFS;
// DAC channels (DRS4 MEZZ1 (fBoardType 6) : DAC_ONOFS,DAC_CMOFSP,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_CMOFSN,DAC_ROFS_1)
unsigned int fDAC_CMOFSP;
unsigned int fDAC_CMOFSN;
// DAC channels (DRS4 EVAL4 (fBoardType 8) : DAC_ONOFS,DAC_TLEVEL4,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL1,DAC_TLEVEL2,DAC_TLEVEL3)
unsigned int fDAC_TLEVEL1;
unsigned int fDAC_TLEVEL2;
unsigned int fDAC_TLEVEL3;
unsigned int fDAC_TLEVEL4;
protected:
// Fields for DRS
int fDRSType;
int fBoardType;
int fNumberOfChips;
int fNumberOfChannels;
int fRequiredFirmwareVersion;
int fFirmwareVersion;
int fBoardSerialNumber;
int fHasMultiBuffer;
unsigned int fTransport;
unsigned int fCtrlBits;
int fNumberOfReadoutChannels;
int fReadoutChannelConfig;
int fADCClkPhase;
bool fADCClkInvert;
double fExternalClockFrequency;
#ifdef HAVE_USB
MUSB_INTERFACE *fUsbInterface;
#endif
#ifdef HAVE_VME
MVME_INTERFACE *fVmeInterface;
mvme_addr_t fBaseAddress;
#endif
int fSlotNumber;
double fNominalFrequency;
double fTrueFrequency;
double fTCALFrequency;
double fRefClock;
int fMultiBuffer;
int fDominoMode;
int fDominoActive;
int fADCActive;
int fChannelConfig;
int fChannelCascading;
int fChannelDepth;
int fWSRLoop;
int fReadoutMode;
unsigned short fReadPointer;
int fNMultiBuffer;
int fTriggerEnable1;
int fTriggerEnable2;
int fTriggerSource;
int fTriggerDelay;
double fTriggerDelayNs;
int fSyncDelay;
int fDelayedStart;
int fTranspMode;
int fDecimation;
unsigned short fStopCell[4];
unsigned char fStopWSR[4];
unsigned short fTriggerBus;
double fROFS;
double fRange;
double fCommonMode;
int fAcalMode;
int fbkAcalMode;
double fAcalVolt;
double fbkAcalVolt;
int fTcalFreq;
int fbkTcalFreq;
int fTcalLevel;
int fbkTcalLevel;
int fTcalPhase;
int fTcalSource;
int fRefclk;
unsigned char fWaveforms[kNumberOfChipsMax * kNumberOfChannelsMax * 2 * kNumberOfBins];
// Fields for Calibration
int fMaxChips;
char fCalibDirectory[1000];
// Fields for Response Calibration old method
ResponseCalibration *fResponseCalibration;
// Fields for Calibration new method
bool fVoltageCalibrationValid;
double fCellCalibratedRange;
double fCellCalibratedTemperature;
unsigned short fCellOffset[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
unsigned short fCellOffset2[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
double fCellGain[kNumberOfChipsMax * kNumberOfChannelsMax][kNumberOfBins];
double fTimingCalibratedFrequency;
double fCellDT[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
// Fields for Time Calibration
TimeData **fTimeData;
int fNumberOfTimeData;
// General debugging flag
int fDebug;
// Fields for wave transfer
bool fWaveTransferred[kNumberOfChipsMax * kNumberOfChannelsMax];
// Waveform Rotation
int fTriggerStartBin; // Start Bin of the trigger
private:
DRSBoard(const DRSBoard &c); // not implemented
DRSBoard &operator=(const DRSBoard &rhs); // not implemented
public:
// Public Methods
#ifdef HAVE_USB
DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot);
#endif
#ifdef HAVE_VME
DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number);
MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; };
#endif
~DRSBoard();
int SetBoardSerialNumber(unsigned short serialNumber);
int GetBoardSerialNumber() const { return fBoardSerialNumber; }
int HasMultiBuffer() const { return fHasMultiBuffer; }
int GetFirmwareVersion() const { return fFirmwareVersion; }
int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; }
int GetDRSType() const { return fDRSType; }
int GetBoardType() const { return fBoardType; }
int GetNumberOfChips() const { return fNumberOfChips; }
// channel : Flash ADC index
// readout channel : VME readout index
// input : Input on board
int GetNumberOfChannels() const { return fNumberOfChannels; }
int GetChannelDepth() const { return fChannelDepth; }
int GetChannelCascading() const { return fChannelCascading; }
inline int GetNumberOfReadoutChannels() const;
inline int GetWaveformBufferSize() const;
inline int GetNumberOfInputs() const;
inline int GetNumberOfCalibInputs() const;
inline int GetClockChannel() const;
inline int GetTriggerChannel() const;
inline int GetClockInput() const { return Channel2Input(GetClockChannel()); }
inline int GetTriggerInput() const { return fDRSType < 4 ? Channel2Input(GetTriggerChannel()) : -1; }
inline int Channel2Input(int channel) const;
inline int Channel2ReadoutChannel(int channel) const;
inline int Input2Channel(int input, int ind = 0) const;
inline int Input2ReadoutChannel(int input, int ind = 0) const;
inline int ReadoutChannel2Channel(int readout) const;
inline int ReadoutChannel2Input(int readout) const;
inline bool IsCalibChannel(int ch) const;
inline bool IsCalibInput(int input) const;
int GetSlotNumber() const { return fSlotNumber; }
int InitFPGA(void);
int Write(int type, unsigned int addr, void *data, int size);
int Read(int type, void *data, unsigned int addr, int size);
int GetTransport() const { return fTransport; }
void RegisterTest(void);
int RAMTest(int flag);
int ChipTest();
unsigned int GetCtrlReg(void);
unsigned short GetConfigReg(void);
unsigned int GetStatusReg(void);
void SetLED(int state);
int SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels);
void SetADCClkPhase(int phase, bool invert);
void SetWarmup(unsigned int ticks);
void SetCooldown(unsigned int ticks);
int GetReadoutChannelConfig() { return fReadoutChannelConfig; }
void SetNumberOfChannels(int nChannels);
int EnableTrigger(int flag1, int flag2);
int GetTriggerEnable(int i) { return i?fTriggerEnable2:fTriggerEnable1; }
int SetDelayedTrigger(int flag);
int SetTriggerDelayPercent(int delay);
int SetTriggerDelayNs(int delay);
int GetTriggerDelay() { return fTriggerDelay; }
double GetTriggerDelayNs() { return fTriggerDelayNs; }
int SetSyncDelay(int ticks);
int SetTriggerLevel(double value);
int SetIndividualTriggerLevel(int channel, double voltage);
int SetTriggerPolarity(bool negative);
int SetTriggerSource(int source);
int GetTriggerSource() { return fTriggerSource; }
int SetDelayedStart(int flag);
int SetTranspMode(int flag);
int SetStandbyMode(int flag);
int SetDecimation(int flag);
int GetDecimation() { return fDecimation; }
int IsBusy(void);
int IsEventAvailable(void);
int IsPLLLocked(void);
int IsLMKLocked(void);
int IsNewFreq(unsigned char chipIndex);
int SetDAC(unsigned char channel, double value);
int ReadDAC(unsigned char channel, double *value);
int GetRegulationDAC(double *value);
int StartDomino();
int StartClearCycle();
int FinishClearCycle();
int Reinit();
int Init();
void SetDebug(int debug) { fDebug = debug; }
int Debug() { return fDebug; }
int SetDominoMode(unsigned char mode);
int SetDominoActive(unsigned char mode);
int SetReadoutMode(unsigned char mode);
int SoftTrigger(void);
int ReadFrequency(unsigned char chipIndex, double *f);
int SetFrequency(double freq, bool wait);
double VoltToFreq(double volt);
double FreqToVolt(double freq);
double GetNominalFrequency() const { return fNominalFrequency; }
double GetTrueFrequency();
int RegulateFrequency(double freq);
int SetExternalClockFrequency(double frequencyMHz);
double GetExternalClockFrequency();
int SetMultiBuffer(int flag);
int IsMultiBuffer() { return fMultiBuffer; }
void ResetMultiBuffer(void);
int GetMultiBufferRP(void);
int SetMultiBufferRP(unsigned short rp);
int GetMultiBufferWP(void);
void IncrementMultiBufferRP(void);
void SetVoltageOffset(double offset1, double offset2);
int SetInputRange(double center);
double GetInputRange(void) { return fRange; }
double GetCalibratedInputRange(void) { return fCellCalibratedRange; }
double GetCalibratedTemperature(void) { return fCellCalibratedTemperature; }
double GetCalibratedFrequency(void) { return fTimingCalibratedFrequency; }
int TransferWaves(int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax);
int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChipsMax * kNumberOfChannelsMax);
int TransferWaves(int firstChannel, int lastChannel);
int TransferWaves(unsigned char *p, int firstChannel, int lastChannel);
int DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
unsigned short *waveform);
int DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform);
int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform,
bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false,
float threshold = 0, bool offsetCalib = true);
int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform,
bool responseCalib = false, int triggerCell = -1, int wsr = -1, bool adjustToClock = false,
float threshold = 0, bool offsetCalib = true);
int GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false,
int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true);
int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
int triggerCell = -1, int wsr = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true);
int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform);
int GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform, bool adjustToClock = false);
int GetRawWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel,
unsigned short *waveform, bool adjustToClock = false);
bool IsTimingCalibrationValid(void);
bool IsVoltageCalibrationValid(void) { return fVoltageCalibrationValid; }
int GetTime(unsigned int chipIndex, int channelIndex, double freq, int tc, float *time, bool tcalibrated=true, bool rotated=true);
int GetTime(unsigned int chipIndex, int channelIndex, int tc, float *time, bool tcalibrated=true, bool rotated=true);
int GetTimeCalibration(unsigned int chipIndex, int channelIndex, int mode, float *time, bool force=false);
int GetTriggerCell(unsigned int chipIndex);
int GetStopCell(unsigned int chipIndex);
unsigned char GetStopWSR(unsigned int chipIndex);
int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex);
void TestDAC(int channel);
void MeasureSpeed();
void InteractSpeed();
void MonitorFrequency();
int TestShift(int n);
int EnableAcal(int mode, double voltage);
int GetAcalMode() { return fAcalMode; }
double GetAcalVolt() { return fAcalVolt; }
int EnableTcal(int freq, int level=0, int phase=0);
int SelectClockSource(int source);
int SetRefclk(int source);
int GetRefclk() { return fRefclk; }
int GetTcalFreq() { return fTcalFreq; }
int GetTcalLevel() { return fTcalLevel; }
int GetTcalPhase() { return fTcalPhase; }
int GetTcalSource() { return fTcalSource; }
int SetCalibVoltage(double value);
int SetCalibTiming(int t1, int t2);
double GetTemperature();
int Is2048ModeCapable();
int GetTriggerBus();
unsigned int GetScaler(int channel);
int ReadEEPROM(unsigned short page, void *buffer, int size);
int WriteEEPROM(unsigned short page, void *buffer, int size);
bool HasCorrectFirmware();
int ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase);
bool InitTimeCalibration(unsigned int chipIndex);
void SetCalibrationDirectory(const char *calibrationDirectoryPath);
void GetCalibrationDirectory(char *calibrationDirectoryPath);
ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; }
double GetPrecision() const { return fResponseCalibration ? fResponseCalibration->GetPrecision() : 0.1; }
int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
short *waveform, bool responseCalib, int triggerCell, bool adjustToClock,
float threshold, bool offsetCalib);
static void LinearRegression(double *x, double *y, int n, double *a, double *b);
void ReadSingleWaveform(int nChips, int nChan,
unsigned short wfu[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins], bool rotated);
int AverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated);
int RobustAverageWaveforms(DRSCallback *pcb, int chipIndex, int nChan, int prog1, int prog2, unsigned short *awf, int n, bool rotated);
int CalibrateVolt(DRSCallback *pcb);
int AnalyzePeriod(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]);
int AnalyzeSlope(Averager *ave, int iIter, int nIter, int channel, float wf[kNumberOfBins], int tCell, double cellDV[kNumberOfBins], double cellDT[kNumberOfBins]);
int CalibrateTiming(DRSCallback *pcb);
static void RemoveSymmetricSpikes(short **wf, int nwf,
short diffThreshold, int spikeWidth,
short maxPeakToPeak, short spikeVoltage,
int nTimeRegionThreshold);
protected:
// Protected Methods
void ConstructBoard();
void ReadSerialNumber();
void ReadCalibration(void);
TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false);
int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period);
};
int DRSBoard::GetNumberOfReadoutChannels() const
{
return (fDRSType == 4 && fReadoutChannelConfig == 4) ? 5 : fNumberOfChannels;
}
int DRSBoard::GetWaveformBufferSize() const
{
int nbin=0;
if (fDRSType < 4) {
nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins;
} else {
if (fBoardType == 6) {
if (fDecimation) {
nbin = fNumberOfChips * (4 * kNumberOfBins + kNumberOfBins / 2);
} else {
nbin = fNumberOfChips * 5 * kNumberOfBins;
}
} else if (fBoardType == 7 || fBoardType == 8 || fBoardType == 9)
nbin = fNumberOfChips * fNumberOfChannels * kNumberOfBins;
}
return nbin * static_cast<int>(sizeof(short int));
}
int DRSBoard::GetNumberOfInputs() const
{
// return number of input channels excluding clock and trigger channels.
if (fDRSType < 4) {
return fNumberOfChannels - 2;
} else {
return fNumberOfChannels / 2;
}
}
int DRSBoard::GetNumberOfCalibInputs() const
{
return (fDRSType < 4) ? 2 : 1;
}
int DRSBoard::GetClockChannel() const
{
return fDRSType < 4 ? 9 : 8;
}
int DRSBoard::GetTriggerChannel() const
{
return fDRSType < 4 ? 8 : -1;
}
int DRSBoard::Channel2Input(int channel) const
{
return (fDRSType < 4) ? channel : channel / 2;
}
int DRSBoard::Channel2ReadoutChannel(int channel) const
{
if (fDRSType < 4) {
return channel;
} else {
if (fReadoutChannelConfig == 4) {
return channel / 2;
} else {
return channel;
}
}
}
int DRSBoard::Input2Channel(int input, int ind) const
{
if (fChannelCascading == 1) {
return (fDRSType < 4) ? input : (input * 2 + ind);
} else {
if (input == 4) { // clock
return 8;
} else {
return input;
}
}
}
int DRSBoard::Input2ReadoutChannel(int input, int ind) const
{
if (fDRSType < 4) {
return input;
} else {
if (fReadoutChannelConfig == 4) {
return input;
} else {
return (input * 2 + ind);
}
}
}
int DRSBoard::ReadoutChannel2Channel(int readout) const
{
if (fDRSType < 4) {
return readout;
} else {
if (fReadoutChannelConfig == 4) {
return readout * 2;
} else {
return readout;
}
}
}
int DRSBoard::ReadoutChannel2Input(int readout) const
{
if (fDRSType < 4) {
return readout;
} else {
if (fReadoutChannelConfig == 4) {
return readout;
} else {
return readout / 2;
}
}
}
bool DRSBoard::IsCalibChannel(int ch) const
{
// return if it is clock or trigger channel
if (fDRSType < 4)
return ch == GetClockChannel() || ch == GetTriggerChannel();
else
return ch == GetClockChannel();
}
bool DRSBoard::IsCalibInput(int input) const
{
// return if it is clock or trigger channel
int ch = Input2Channel(input);
if (fDRSType < 4)
return ch == GetClockChannel() || ch == GetTriggerChannel();
else
return ch == GetClockChannel();
}
class DRS {
protected:
// constants
enum {
kMaxNumberOfBoards = 40
};
protected:
DRSBoard *fBoard[kMaxNumberOfBoards];
int fNumberOfBoards;
char fError[256];
#ifdef HAVE_VME
MVME_INTERFACE *fVmeInterface;
#endif
private:
DRS(const DRS &c); // not implemented
DRS &operator=(const DRS &rhs); // not implemented
public:
// Public Methods
DRS();
~DRS();
DRSBoard *GetBoard(int i) { return fBoard[i]; }
void SetBoard(int i, DRSBoard *b);
DRSBoard **GetBoards() { return fBoard; }
int GetNumberOfBoards() const { return fNumberOfBoards; }
bool GetError(char *str, int size);
void SortBoards();
#ifdef HAVE_VME
MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; };
#endif
};
#endif // DRS_H