source: drsdaq/DRS/DRS.cc@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 121.6 KB
Line 
1
2/********************************************************************\
3
4 Name: DRS.cc
5
6 Created by: Stefan Ritt, Matthias Schneebeli
7
8 Modified by: Sebastian Commichau, May-November 2008
9 commichau@phys.ethz.ch
10
11 Modification: This library works with:
12 - Concurrent Technolgies VME single board PC (VP 315)
13 - Struck VME controller (SIS 3100) => faster!
14
15 Contents: Library functions for DRS board CMC card - requires
16 DRS version 2 or 3
17
18\********************************************************************/
19
20#include "DRS.h"
21
22#define DEBUG 0
23
24// Minimal FPGA firmware version required for this library
25#define REQUIRED_FIRMWARE_VERSION_DRS2 5268
26#define REQUIRED_FIRMWARE_VERSION_DRS3 6981
27
28#ifdef CT_VME
29#define MEM_SEGMENT 0XA000 // Size of the memory segment allocated by each DRS board for BLT
30#define BLT_TIMEOUT 1000 // Timeout for BLT [msec]
31#endif
32
33int drs_kbhit()
34{
35 int n;
36
37 ioctl(0, FIONREAD, &n);
38 return (n > 0);
39}
40
41static inline int getch() { return getchar(); }
42inline void Sleep(useconds_t x) { usleep(x * 1000); }
43
44// VME addresses
45
46/* Assuming following DIP Switch settings:
47
48SW1-1: 1 (off) Use geographical addressing (1=left, 21=right)
49SW1-2: 1 (off) \
50SW1-3: 1 (off) > VME_WINSIZE = 8MB, subwindow = 1MB
51SW1-4: 0 (on) /
52SW1-5: 0 (on) Reserved
53SW1-6: 0 (on) Reserved
54SW1-7: 0 (on) Reserved
55SW1-8: 0 (on) \
56SW2-1: 0 (on) |
57SW2-2: 0 (on) |
58SW2-3: 0 (on) |
59SW2-4: 0 (on) > VME_ADDR_OFFSET = 0
60SW2-5: 0 (on) |
61SW2-6: 0 (on) |
62SW2-7: 0 (on) |
63SW2-8: 0 (on) /
64
65which gives
66VME base address = SlotNo * VME_WINSIZE + VME_ADDR_OFFSET
67= SlotNo * 0x80'0000 */
68
69#define GEVPC_BASE_ADDR 0x00000000
70#define GEVPC_WINSIZE 0x800000
71#define GEVPC_USER_FPGA (GEVPC_WINSIZE*2/8)
72#define PMC1_OFFSET 0x00000
73#define PMC2_OFFSET 0x80000
74#define PMC_CTRL_OFFSET 0x00000 // All registers 32 bit!
75#define PMC_STATUS_OFFSET 0x10000
76#define PMC_FIFO_OFFSET 0x20000
77#define PMC_RAM_OFFSET 0x40000
78
79// DRS registers
80#define T_CTRL 1
81#define T_STATUS 2
82#define T_RAM 3
83#define T_FIFO 4
84#define REG_CTRL 0x00000 // 32-bit control reg
85#define REG_DAC_OFS 0x00004
86#define REG_DAC0 0x00004
87#define REG_DAC1 0x00006
88#define REG_DAC2 0x00008
89#define REG_DAC3 0x0000A
90#define REG_DAC4 0x0000C
91#define REG_DAC5 0x0000E
92#define REG_DAC6 0x00010
93#define REG_DAC7 0x00012
94#define REG_CHANNEL_CONFIG 0x00014
95#define REG_CHANNEL_SPAN 0x00016
96#define REG_FREQ_SET_HI 0x00018
97#define REG_FREQ_SET_LO 0x0001A
98#define REG_TRIG_DELAY 0x0001C
99#define REG_CALIB_TIMING 0x0001E
100#define REG_STATUS 0x00000
101#define REG_RDAC_OFS 0x0000A
102#define REG_RDAC0 0x00004
103#define REG_RDAC1 0x00006
104#define REG_RDAC2 0x00008
105#define REG_RDAC3 0x0000A
106#define REG_RDAC4 0x0000C
107#define REG_RDAC5 0x0000E
108#define REG_RDAC6 0x00010
109#define REG_RDAC7 0x00012
110#define REG_EVENTS_IN_FIFO 0x00014
111#define REG_EVENT_COUNT 0x00016
112#define REG_FREQ1 0x00018
113#define REG_FREQ2 0x0001A
114#define REG_TEMPERATURE 0x0001C
115#define REG_TRIGGER_BUS 0x0001E
116#define REG_SERIAL_CMC 0x00020
117#define REG_VERSION_FW 0x00022
118
119using namespace std;
120
121
122DRS::DRS() : fNumberOfBoards(0),
123#ifdef STRUCK_VME
124 fVMEInterface(0),
125#endif
126 First_VME_Slot(0), Last_VME_Slot(7)
127{ }
128
129
130/*------------------------------------------------------------------*/
131
132DRS::~DRS() {
133
134 int i;
135
136 for (i = 0; i < fNumberOfBoards; i++) {
137 delete fBoard[i];
138 }
139
140#ifdef CT_VME
141 if (!CloseVME())
142 printf("VME connection closed\n");
143
144 if (!CloseCMEM())
145 printf("CMEM closed\n");
146#endif
147
148#ifdef STRUCK_VME
149 if (fVMEInterface != NULL)
150 if (mvme_close(fVMEInterface));
151 printf("VME connection closed\n");
152
153#endif
154
155}
156
157/*------------------------------------------------------------------*/
158#ifdef CT_VME
159int DRS::OpenVME() {
160
161 // Open VME connection
162 if ((ErrorCode = VME_Open()) != VME_SUCCESS) {
163
164 VME_ErrorString(ErrorCode,ErrorString);
165
166 printf("Error: %s\n",ErrorString);
167 }
168
169 return ErrorCode;
170}
171#endif
172/*------------------------------------------------------------------*/
173
174void DRS::InitialScan() {
175
176 int index = 0;
177
178 unsigned short Firmware, Serial, Temperature;
179
180#ifdef CT_VME
181
182 unsigned int BoardAddress;
183
184 if (!OpenVME()) {
185
186 printf("VME connection opened\n");
187
188 if (!OpenCMEM())
189 printf("CMEM opened\n");
190 else return;
191
192 // Set master mapping input information
193 MasterMap.vmebus_address = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // Init VME board base address (derived from
194 // the slot number => geographical addressing)
195
196 MasterMap.window_size = GEVPC_WINSIZE; // VME address window size
197
198 MasterMap.address_modifier = VME_A32;
199 MasterMap.options = 0;
200
201
202 // Check all VME slave slots
203 for (index = First_VME_Slot; index <= Last_VME_Slot; index++) {
204
205
206 MasterMap.vmebus_address = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // Update VME board base address
207
208
209 if (DEBUG)
210 printf("Checking VME slot %d (base address: 0X%08X)\n",index,MasterMap.vmebus_address);
211
212 MasterMapVME(&MasterMapping[index]);
213
214 // **************************** Check PMC1 ****************************
215 BoardAddress = GEVPC_USER_FPGA; // UsrFPGA base address
216 BoardAddress += PMC1_OFFSET; // PMC1 offset
217
218 // Read firmware
219 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_VERSION_FW, &Firmware);
220
221 // Read serial number
222 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_SERIAL_CMC, &Serial);
223
224 // Read temperature register to see if CMC card is present
225 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_TEMPERATURE, &Temperature);
226
227 if (Firmware > 2400 && Firmware < 20000) {
228
229 if (Temperature == 0XFFFF) {
230 if (DEBUG)
231 printf("No CMC board in slot %d\n", index);
232 } else {
233 if (DEBUG) {
234 printf("Found CMC board in slot %d:\n", index);
235 printf(" Firmware: %d\n",Firmware);
236 printf(" Board serial nr.: %d\n",Serial);
237 printf(" Temperature register: %d\n",Temperature);
238 }
239
240 fBoard[fNumberOfBoards] = new DRSBoard(MasterMapping[index], MasterMap.vmebus_address, BoardAddress, (index-2) << 1);
241
242 if (fBoard[fNumberOfBoards]->HasCorrectFirmware())
243 fNumberOfBoards++;
244 else
245 if (DEBUG)
246 printf("Error: wrong firmware version: board has %d, required is %d\n",
247 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
248 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
249 }
250 }
251
252
253 // **************************** Check PMC2 ****************************
254 BoardAddress = GEVPC_USER_FPGA; // UsrFPGA base address
255 BoardAddress += PMC2_OFFSET; // PMC2 offset
256
257 // Read firmware
258 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_VERSION_FW, &Firmware);
259
260 // Read serial number
261 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_SERIAL_CMC, &Serial);
262
263 // Read temperature register to see if CMC card is present
264 VME_ReadFastUShort(MasterMapping[index], BoardAddress + PMC_STATUS_OFFSET + REG_TEMPERATURE, &Temperature);
265
266 if (Firmware > 2400 && Firmware < 20000) {
267
268 if (Temperature == 0XFFFF) {
269 printf("No CMC board in slot %d\n", index);
270 } else {
271 if (DEBUG) {
272 printf("Found CMC board in slot %d:\n", index);
273 printf(" Firmware: %d\n",Firmware);
274 printf(" Board serial nr.: %d\n",Serial);
275 printf(" Temperature register: %d\n",Temperature);
276 }
277
278 fBoard[fNumberOfBoards] = new DRSBoard(MasterMapping[index], MasterMap.vmebus_address, BoardAddress, ((index-2) << 1) | 1);
279
280 if (fBoard[fNumberOfBoards]->HasCorrectFirmware())
281 fNumberOfBoards++;
282 else
283 if (DEBUG)
284 printf("Error: wrong firmware version: board has %d, required is %d\n",
285 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
286 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
287 }
288 }
289 else
290 MasterUnMapVME(MasterMapping[index]);
291 }
292 if (DEBUG) printf("Found %d DRS boards in VME crate\n", fNumberOfBoards);
293 }
294#endif
295#ifdef STRUCK_VME
296
297 int i = 0;
298
299 mvme_addr_t Address;
300
301 if (mvme_open(&fVMEInterface, 0) == MVME_SUCCESS) {
302
303 printf("VME connection opened\n");
304
305 mvme_set_am(fVMEInterface, MVME_AM_A32);
306 mvme_set_dmode(fVMEInterface, MVME_DMODE_D16);
307
308 // Check all VME slave slots
309 for (index = 2; index <= 21; index++) {
310
311 // **************************** Check PMC1 ****************************
312 Address = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
313 Address += GEVPC_USER_FPGA; // UsrFPGA base address
314 Address += PMC1_OFFSET; // PMC1 offset
315
316 // Read firmware
317 i = mvme_read(fVMEInterface, &Firmware, Address + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);
318
319 if (i == 2) {
320
321 // Read serial number
322 mvme_read(fVMEInterface, &Serial, Address + PMC_STATUS_OFFSET + REG_SERIAL_CMC, 2);
323
324 // Read temperature register to see if CMC card is present
325 mvme_read(fVMEInterface, &Temperature, Address + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);
326
327 if (Firmware > 2400 && Firmware < 20000) {
328
329 if (Temperature == 0xFFFF) {
330 printf("No CMC board in slot %d\n", index);
331 } else {
332 if (DEBUG) {
333 printf("Found CMC board in slot %d:\n", index);
334 printf(" Firmware: %d\n",Firmware);
335 printf(" Board serial nr.: %d\n",Serial);
336 printf(" Temperature register: %d\n",Temperature);
337 }
338
339 fBoard[fNumberOfBoards] = new DRSBoard(fVMEInterface, Address, (index-2) << 1);
340
341 if (fBoard[fNumberOfBoards]->HasCorrectFirmware())
342 fNumberOfBoards++;
343 else
344 if (DEBUG)
345 printf("Error: wrong firmware version: board has %d, required is %d\n",
346 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
347 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
348
349 }
350 }
351 }
352
353 // **************************** Check PMC2 ****************************
354 Address = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
355 Address += GEVPC_USER_FPGA; // UsrFPGA base address
356 Address += PMC2_OFFSET; // PMC2 offset
357
358 // Read firmware
359 i = mvme_read(fVMEInterface, &Firmware, Address + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);
360
361 if (i == 2) {
362
363 // Read serial number
364 mvme_read(fVMEInterface, &Serial, Address + PMC_STATUS_OFFSET + REG_SERIAL_CMC, 2);
365
366 // Read temperature register to see if CMC card is present
367 mvme_read(fVMEInterface, &Temperature, Address + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);
368
369 if (Firmware > 2400 && Firmware < 20000) {
370
371 if (Temperature == 0xFFFF) {
372 printf("No CMC board in slot %d\n", index);
373 } else {
374 if (DEBUG) {
375 printf("Found CMC board in slot %d:\n", index);
376 printf(" Firmware: %d\n",Firmware);
377 printf(" Board serial nr.: %d\n",Serial);
378 printf(" Temperature register: %d\n",Temperature);
379 }
380
381 fBoard[fNumberOfBoards] = new DRSBoard(fVMEInterface, Address, ((index-2) << 1) | 1);
382
383 if (fBoard[fNumberOfBoards]->HasCorrectFirmware())
384 fNumberOfBoards++;
385 else
386 if (DEBUG)
387 printf("Error: wrong firmware version: board has %d, required is %d\n",
388 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
389 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
390 }
391 }
392 }
393 }
394 if (DEBUG) printf("Found %d DRS boards in VME crate\n", fNumberOfBoards);
395 }
396#endif
397 else printf("Error: cannot access VME crate, check driver, power and connection\n");
398
399}
400
401/*------------------------------------------------------------------*/
402
403#ifdef CT_VME
404int DRS::MasterMapVME(int *MMap) {
405
406 // Do master mapping
407 if (ErrorCode = VME_MasterMap(&MasterMap, MMap)) {
408
409 VME_ErrorString(ErrorCode,ErrorString);
410
411 printf("Error: %s\n",ErrorString);
412 }
413
414 return(ErrorCode);
415}
416#endif
417
418/*------------------------------------------------------------------*/
419
420#ifdef CT_VME
421int DRS::MasterUnMapVME(int MMap) {
422
423 // Delete master mapping
424 if (ErrorCode = VME_MasterUnmap(MMap)) {
425
426 VME_ErrorString(ErrorCode,ErrorString);
427
428 printf("Error: %s\n",ErrorString);
429 }
430
431 return(ErrorCode);
432}
433#endif
434
435/*------------------------------------------------------------------*/
436
437#ifdef CT_VME
438int DRS::CloseVME() {
439
440 // Close VME connection
441 if ((ErrorCode = VME_Close()) != VME_SUCCESS) {
442
443 VME_ErrorString(ErrorCode,ErrorString);
444
445 printf("Error: %s\n",ErrorString);
446 }
447
448 return ErrorCode;
449}
450#endif
451
452/*------------------------------------------------------------------*/
453
454#ifdef CT_VME
455int DRS::OpenCMEM() {
456
457 // Open CMEM package
458 if ((ErrorCode = CMEM_Open()) != CMEM_RCC_SUCCESS) {
459
460 VME_ErrorString(ErrorCode,ErrorString);
461
462 printf("Error: %s\n",ErrorString);
463 }
464
465 return ErrorCode;
466}
467#endif
468
469/*------------------------------------------------------------------*/
470
471#ifdef CT_VME
472int DRS::CloseCMEM() {
473
474 // Close CMEM package
475 if ((ErrorCode = CMEM_Close()) != CMEM_RCC_SUCCESS) {
476
477 VME_ErrorString(ErrorCode,ErrorString);
478
479 printf("Error: %s\n",ErrorString);
480 }
481
482 return ErrorCode;
483}
484#endif
485
486/*------------------------------------------------------------------*/
487
488#ifdef CT_VME
489DRSBoard::DRSBoard(int MasterMapping, unsigned int BaseAddress, unsigned int BoardAddress, int SlotNumber)
490#else
491DRSBoard::DRSBoard(MVME_INTERFACE *MVME_Interface, mvme_addr_t BaseAddress, int SlotNumber)
492#endif
493 :fDAC_COFSA(0)
494 ,fDAC_COFSB(0)
495 ,fDAC_DRA(0)
496 ,fDAC_DSA(0)
497 ,fDAC_TLEVEL(0)
498 ,fDAC_ACALIB(0)
499 ,fDAC_DSB(0)
500 ,fDAC_DRB(0)
501 ,fDAC_COFS(0)
502 ,fDAC_ADCOFS(0)
503 ,fDAC_CLKOFS(0)
504 ,fDAC_ROFS_1(0)
505 ,fDAC_ROFS_2(0)
506 ,fDAC_INOFS(0)
507 ,fDAC_BIAS(0)
508 ,fRequiredFirmwareVersion(0)
509 ,fFirmwareVersion(0)
510 ,fChipVersion(0)
511 ,fBoardVersion(0)
512 ,fCMCSerialNumber(0)
513 ,fCtrlBits(0)
514 ,fNumberOfReadoutChannels(0)
515 ,fExternalClockFrequency(0)
516 ,fBaseAddress(BaseAddress)
517#ifdef CT_VME
518 ,fBoardAddress(BoardAddress)
519 ,fMasterMapping(MasterMapping)
520 ,fSlotNumber(SlotNumber)
521#endif
522#ifdef STRUCK_VME
523 ,fVMEInterface(MVME_Interface)
524 ,fSlotNumber(SlotNumber)
525#endif
526 ,fFrequency(0)
527 ,fDominoMode(0)
528 ,fReadoutMode(0)
529 ,fTriggerEnable(0)
530 ,fDelayedStart(0)
531 ,fTriggerCell(0)
532 ,fMaxChips(0)
533 ,fResponseCalibration(0)
534 ,fTimeData(0)
535 ,fNumberOfTimeData(0)
536 ,fDebug(0)
537 ,fTriggerStartBin(0)
538 ,kRotateWave(0)
539{
540 ConstructBoard();
541}
542
543
544/*------------------------------------------------------------------*/
545
546DRSBoard::~DRSBoard()
547{
548 // Response Calibration
549 delete fResponseCalibration;
550
551 int i;
552 // Time Calibration
553 for (i = 0; i < fNumberOfTimeData; i++) {
554 delete fTimeData[i];
555 }
556 delete[]fTimeData;
557
558#ifdef CT_VME
559 if (!FreeSegmentCMEM(CMEM_SegIdentifier) && DEBUG)
560 printf("Memory segment %d (board #%d) freed\n",CMEM_SegIdentifier,fCMCSerialNumber);
561#endif
562}
563
564/*------------------------------------------------------------------*/
565
566void DRSBoard::ConstructBoard()
567{
568 fDebug = 0;
569 fDominoMode = 1;
570 fReadoutMode = 0;
571 fTriggerEnable = 0;
572 fCtrlBits = 0;
573 fNumberOfReadoutChannels = 10;
574 fExternalClockFrequency = 1000. / 30.;
575
576 for (int i = 0; i < kNumberOfChips * kNumberOfChannels; i++)
577 fWaveTransferred[i] = false;
578
579 strcpy(fCalibDirectory, ".");
580
581#ifdef CT_VME
582 if (DEBUG) {
583 printf("Base address: 0X%08X\n",fBaseAddress);
584 printf("Board address: 0X%08X\n",fBoardAddress);
585 printf("0X%08X\n",fBaseAddress+fBoardAddress);
586 }
587#endif
588 ReadSerialNumber();
589
590 // Check for required firmware version
591 if (!HasCorrectFirmware())
592 return;
593
594 if (DEBUG)
595 printf("Board version: %d\n",fBoardVersion);
596
597 if (fBoardVersion == 1) {
598
599 fDAC_COFSA = 0;
600 fDAC_COFSB = 1;
601 fDAC_DRA = 2;
602 fDAC_DSA = 3;
603 fDAC_TLEVEL = 4;
604 fDAC_ACALIB = 5;
605 fDAC_DSB = 6;
606 fDAC_DRB = 7;
607
608 } else if (fBoardVersion == 2 || fBoardVersion == 3) {
609
610 fDAC_COFS = 0;
611 fDAC_DSA = 1;
612 fDAC_DSB = 2;
613 fDAC_TLEVEL = 3;
614 fDAC_CLKOFS = 5;
615 fDAC_ACALIB = 6;
616 fDAC_ADCOFS = 7;
617
618 } else if (fBoardVersion == 4) {
619
620 fDAC_ROFS_1 = 0;
621 fDAC_DSA = 1;
622 fDAC_DSB = 2;
623 fDAC_ROFS_2 = 3;
624 fDAC_BIAS = 4;
625 fDAC_ADCOFS = 7;
626 fDAC_INOFS = 5;
627 fDAC_ACALIB = 6;
628 }
629
630 // Response Calibration
631 fResponseCalibration = new ResponseCalibration(this);
632
633 // Time Calibration
634 fTimeData = new DRSBoard::TimeData *[kNumberOfChips];
635 fNumberOfTimeData = 0;
636
637#ifdef CT_VME
638 // Allocate contiguous memory for BLT
639 AllocateSegmentCMEM(MEM_SEGMENT,&CMEM_SegIdentifier);
640 if (DEBUG)
641 printf("Memory segment %d (board #%d) allocated\n",CMEM_SegIdentifier,fCMCSerialNumber);
642
643 AssignPhysicalSegAddressCMEM(CMEM_SegIdentifier, &PCIAddress);
644 AssignVirtualSegAddressCMEM(CMEM_SegIdentifier, &VirtualAddress);
645 if (DEBUG)
646 printf("Physical address: 0X%08X, virtual address: 0X%08X\n", (unsigned int)PCIAddress,(unsigned int)VirtualAddress);
647#endif
648
649}
650
651/*------------------------------------------------------------------*/
652
653void DRSBoard::PrintBinary32(unsigned int i) {
654
655 int k;
656
657 for (k=31;k>=0;k--)
658 if ((i & (1 << k)) !=0) {
659 if ((k)%8)
660 printf("1");
661 else
662 printf("1 ");
663 }
664 else {
665 if ((k)%8)
666 printf("0");
667 else
668 printf("0 ");
669 }
670 printf("\n");
671}
672
673/*------------------------------------------------------------------*/
674
675long int DRSBoard::GetMicroSeconds() {
676
677 struct tm * timeinfo;
678 time_t rawtime;
679
680 struct timezone tz;
681 struct timeval actual_time; // Actual time
682
683 gettimeofday(&actual_time, &tz);
684
685 time(&rawtime);
686
687 timeinfo = gmtime(&rawtime); // Get UTC (or GMT timezone).
688
689 return (timeinfo->tm_hour*3600 + timeinfo->tm_min*60 + timeinfo->tm_sec)*1000000 + actual_time.tv_usec;
690
691}
692
693
694/*------------------------------------------------------------------*/
695
696int DRSBoard::TestRead(unsigned int n, int type) {
697
698 float delta;
699 float mbps;
700
701 int errors = 0;
702
703 const int size = 0X10000; // bytes
704
705#ifdef STRUCK_VME
706
707 long int ts1, ts2;
708
709 unsigned int Address = fBaseAddress + PMC_RAM_OFFSET;
710
711 int read = 0, i;
712
713 unsigned char data[size];
714
715 printf("**************************************************\n");
716
717 if (type==0) {
718 mvme_set_dmode(fVMEInterface, MVME_DMODE_D32);
719 mvme_set_blt(fVMEInterface, MVME_BLT_BLT32);
720 printf(" Mode: VMEbus A32/D32 DMA read [64 kB]\n");
721 }
722 else if (type==1) {
723 mvme_set_dmode(fVMEInterface, MVME_DMODE_D32);
724 mvme_set_blt(fVMEInterface,MVME_BLT_MBLT64);
725 printf(" Mode: VMEbus A32/D64 DMA read [64 kB]\n");
726 }
727 else if (type==2) {
728 mvme_set_dmode(fVMEInterface, MVME_DMODE_D64);
729 mvme_set_blt(fVMEInterface, MVME_BLT_2EVME);
730 printf(" Mode: VMEbus A32/D64 2eVME read [64 kB]\n");
731 }
732
733 ts1 = GetMicroSeconds();
734
735 for (unsigned int j=0;j<n;j++) {
736 read = mvme_read(fVMEInterface, static_cast<unsigned char*>(data), Address, size);
737
738 while (read != size) {
739
740 errors++;
741 printf("Only read %d out of %d, retry with %d: ", read, size, size-read);
742 i = mvme_read(fVMEInterface, static_cast<unsigned char*>(data) + read/4, Address + read, size - read);
743 printf("read %d\n", i);
744 if (i == 0) {
745 printf("Error reading VME\n");
746 return read;
747 }
748 read += i;
749 }
750 }
751
752 ts2 = GetMicroSeconds();
753
754 delta = (ts2 - ts1)/1000000.;
755
756 mbps = n * read * 1.0/(delta * 1024. * 1024.);
757
758 printf(" %d BLT(s) finished...\n",n);
759
760 if (!errors)
761 printf(" %d errors... success!\n",errors);
762 else
763 printf(" %d errors...\n",errors);
764
765 printf(" Duration: %.3f s\n", delta);
766 printf(" Rate: %.3f MB/s\n", mbps);
767
768 printf("**************************************************\n");
769
770#endif
771#ifdef CT_VME
772 tstamp ts1, ts2;
773
774 unsigned int ret;
775
776 ret = ts_open(1, TS_DUMMY);
777 if (ret)
778 {
779 rcc_error_print(stdout, ret);
780 exit(-2);
781 }
782
783 printf("**************************************************\n");
784
785 // Assign fields for BLT
786 BLT_List.number_of_items = 1;
787 BLT_List.list_of_items[0].vmebus_address = fBaseAddress + fBoardAddress + PMC_RAM_OFFSET;
788 BLT_List.list_of_items[0].system_iobus_address = PCIAddress;
789 BLT_List.list_of_items[0].size_requested = size;
790
791 if (type==0) {
792 BLT_List.list_of_items[0].control_word = VME_DMA_D32R | VME_A32;
793 printf(" Mode: VMEbus A32/D32 DMA read [64 kB]\n");
794 }
795 else if (type==1) {
796 BLT_List.list_of_items[0].control_word = VME_DMA_D64R | VME_A32;
797 printf(" Mode: VMEbus A32/D64 DMA read [64 kB]\n");
798 }
799 else if (type==2) {
800 printf("Warning: current interface does not support 2exx transfer mode!\n");
801 return 0;
802 }
803
804 printf(" VMEbus address: 0X%08X\n", BLT_List.list_of_items[0].vmebus_address);
805 printf(" Contiguous buffer:\n");
806 printf(" Physical address: 0X%08X\n", (unsigned int)PCIAddress);
807 printf(" Virtual address: 0X%08X\n", (unsigned int)VirtualAddress);
808
809 ts_clock(&ts1);
810
811 for (unsigned int i=0;i<n;i++)
812 // Perfom BLT
813 if ((ErrorCode = VME_BlockTransfer(&BLT_List,BLT_TIMEOUT)) != VME_SUCCESS) {
814 VME_ErrorString(ErrorCode,ErrorString);
815 printf(" VME (BLT): %s\n",ErrorString);
816
817 errors++;
818 return -1;
819 }
820
821 ts_clock(&ts2);
822 delta = ts_duration(ts1, ts2);
823 mbps = n * size * 1.0 / (delta * 1024. * 1024.);
824
825 printf(" %d BLT(s) finished...\n",n);
826
827 if (!errors)
828 printf(" %d errors... success!\n",errors);
829 else
830 printf(" %d errors...\n",errors);
831
832 printf(" Duration: %.3f s\n", delta);
833 printf(" Rate: %.3f MB/s\n", mbps);
834
835 ret = ts_close(TS_DUMMY);
836 if (ret)
837 {
838 rcc_error_print(stdout, ret);
839 exit(-2);
840 }
841
842 printf("**************************************************\n");
843#endif
844
845 return 0;
846}
847
848/*------------------------------------------------------------------*/
849
850void DRSBoard::ReadSerialNumber()
851{
852 unsigned char buffer[2];
853 char str[80];
854 int number;
855
856 Read(T_STATUS, buffer, REG_VERSION_FW, 2);
857 fFirmwareVersion = (static_cast<int>(buffer[1]) << 8) + buffer[0];
858
859 // Retrieve board serial number
860 Read(T_STATUS, buffer, REG_SERIAL_CMC, 2);
861 number = (static_cast<int>(buffer[1]) << 8) + buffer[0];
862 fCMCSerialNumber = number;
863
864 // Determine DRS chip number from serial number
865 fChipVersion = number < 1000 ? 2 : 3;
866
867 if (number == 0xFFFF) {
868 printf("Found new mezzanine board. Please select DRS version (2/[3]): ");
869 fgets(str, sizeof(str), stdin);
870 if (atoi(str) == 2)
871 fChipVersion = 2;
872 else
873 fChipVersion = 3;
874 }
875
876 // Retrieve firmware version
877 if (fChipVersion == 2)
878 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
879 if (fChipVersion == 3)
880 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS3;
881
882
883 // Determine board version from serial number
884 if (number >= 1000)
885 fBoardVersion = 4;
886 else if (number >= 100)
887 fBoardVersion = 3;
888 else if (number > 0)
889 fBoardVersion = 2;
890 else {
891 fBoardVersion = 4;
892 fChipVersion = 3;
893 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS3;
894 }
895
896 //Fixme (SCC 03032008): change function FlashEEPROM accordingly!
897 //fChipVersion = 2;
898 //fBoardVersion = 3;
899 //fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
900}
901
902/*------------------------------------------------------------------*/
903
904bool DRSBoard::HasCorrectFirmware()
905{
906 // Check firmware version
907 return (fFirmwareVersion >= fRequiredFirmwareVersion);
908}
909
910/*------------------------------------------------------------------*/
911
912int DRSBoard::Write(int type, unsigned int addr, void *data, int size)
913{
914
915 // Generic write function
916
917#ifdef CT_VME
918 if (size > MEM_SEGMENT)
919 size = MEM_SEGMENT;
920
921 if (type == T_CTRL)
922 addr += PMC_CTRL_OFFSET;
923 else if (type == T_STATUS)
924 addr += PMC_STATUS_OFFSET;
925 else if (type == T_RAM)
926 addr += PMC_RAM_OFFSET;
927
928 if (size == 1) {
929
930 VME_WriteSafeUChar(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned char*>(data)));
931
932 } else if (size == 2) {
933
934 VME_WriteSafeUShort(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned short*>(data)));
935
936 } else if (size == 4) {
937
938 VME_WriteSafeUInt(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned int*>(data)));
939
940 } else {
941
942 // Copy contiguous block of memory starting from VirtualAddress
943 memcpy((unsigned long*)((unsigned long)VirtualAddress),(unsigned long*)data,size);
944
945 // Assign fields for BLT
946 BLT_List.list_of_items[0].vmebus_address = fBaseAddress + fBoardAddress + PMC_RAM_OFFSET;
947 BLT_List.list_of_items[0].system_iobus_address = PCIAddress;
948 BLT_List.list_of_items[0].size_requested = MEM_SEGMENT;
949 BLT_List.list_of_items[0].control_word = VME_DMA_D64W | VME_A32;
950
951 BLT_List.number_of_items = 1;
952
953 // Perfom BLT
954 if ((ErrorCode = VME_BlockTransfer(&BLT_List,BLT_TIMEOUT)) != VME_SUCCESS) {
955 VME_ErrorString(ErrorCode,ErrorString);
956 printf("VME (BLT): %s\n",ErrorString);
957 }
958 }
959
960#endif
961#ifdef STRUCK_VME
962
963 unsigned int base_addr;
964
965 base_addr = fBaseAddress;
966
967 if (type == T_CTRL)
968 base_addr += PMC_CTRL_OFFSET;
969 else if (type == T_STATUS)
970 base_addr += PMC_STATUS_OFFSET;
971 else if (type == T_RAM)
972 base_addr += PMC_RAM_OFFSET;
973
974 if (size == 1) {
975 // 8-bit write access
976 mvme_set_dmode(fVMEInterface, MVME_DMODE_D8);
977 mvme_write(fVMEInterface, base_addr + addr, static_cast<mvme_locaddr_t*>(data), size);
978 } else if (size == 2) {
979 // 16-bit write access
980 mvme_set_dmode(fVMEInterface, MVME_DMODE_D16);
981 mvme_write(fVMEInterface, base_addr + addr, static_cast<mvme_locaddr_t*>(data), size);
982 } else {
983 mvme_set_dmode(fVMEInterface, MVME_DMODE_D32);
984
985 // As long as no block transfer is supported, do pseudo block transfer
986 mvme_set_blt(fVMEInterface, MVME_BLT_NONE);
987
988 mvme_write(fVMEInterface, base_addr + addr, static_cast<mvme_locaddr_t*>(data), size);
989 }
990
991#endif
992
993 return size;
994}
995
996/*------------------------------------------------------------------*/
997
998int DRSBoard::Read(int type, void *data, unsigned int addr, int size)
999{
1000
1001 // Generic read function
1002
1003#ifdef CT_VME
1004
1005 if (size > MEM_SEGMENT)
1006 size = MEM_SEGMENT;
1007
1008 if (type == T_CTRL)
1009 addr += PMC_CTRL_OFFSET;
1010 else if (type == T_STATUS)
1011 addr += PMC_STATUS_OFFSET;
1012 else if (type == T_RAM) {
1013 addr += PMC_RAM_OFFSET;
1014 }
1015 else if (type == T_FIFO) {
1016 addr += PMC_FIFO_OFFSET;
1017 }
1018
1019 if (size == 1) {
1020
1021 VME_ReadFastUChar(fMasterMapping, fBoardAddress + addr, static_cast<unsigned char*>(data));
1022
1023 } else if (size == 2) {
1024
1025 VME_ReadFastUShort(fMasterMapping, fBoardAddress + addr, static_cast<unsigned short*>(data));
1026
1027 } else if (size == 4) {
1028
1029 VME_ReadFastUInt(fMasterMapping, fBoardAddress + addr, static_cast<unsigned int*>(data));
1030
1031 } else {
1032
1033 // Assign fields for BLT
1034 BLT_List.list_of_items[0].vmebus_address = fBaseAddress + fBoardAddress + PMC_RAM_OFFSET;
1035 BLT_List.list_of_items[0].system_iobus_address = PCIAddress;
1036 BLT_List.list_of_items[0].size_requested = MEM_SEGMENT;
1037 BLT_List.list_of_items[0].control_word = VME_DMA_D64R | VME_A32;
1038
1039 BLT_List.number_of_items = 1;
1040
1041 // Perfom BLT
1042 if ((ErrorCode = VME_BlockTransfer(&BLT_List,BLT_TIMEOUT)) != VME_SUCCESS) {
1043 VME_ErrorString(ErrorCode,ErrorString);
1044 printf("VME (BLT): %s\n",ErrorString);
1045 }
1046
1047 // Copy contiguous block of memory starting from VirtualAddress
1048 memcpy((unsigned long*)data,(unsigned long*)((unsigned long)VirtualAddress),size);
1049
1050 // Do pseudo BLT
1051 /*for (i = 0; i < size; i += 4)
1052 VME_ReadFastUInt(fMasterMapping, fBoardAddress + addr + i, (unsigned int*)((unsigned char*)data + i));
1053
1054 // Decode data
1055 printf("pseudo BLT: %d %d\n",((*((unsigned char*)data + 1) & 0x0f) << 8) | *((unsigned char*)data),
1056 ((*((unsigned char*)data + 2)) << 4) | ((*((unsigned char*)data + 1)) >> 4) );
1057
1058 printf("pseudo BLT: %d %d\n",((*((unsigned char*)data + 5) & 0x0f) << 8) | *((unsigned char*)data + 4),
1059 ((*((unsigned char*)data + 6)) << 4) | ((*((unsigned char*)data + 5)) >> 4) );
1060 */
1061 }
1062 return size;
1063
1064#endif
1065#ifdef STRUCK_VME
1066
1067 unsigned int base_addr;
1068 int n, i;
1069
1070 base_addr = fBaseAddress;
1071
1072 if (type == T_CTRL)
1073 base_addr += PMC_CTRL_OFFSET;
1074 else if (type == T_STATUS)
1075 base_addr += PMC_STATUS_OFFSET;
1076 else if (type == T_RAM)
1077 base_addr += PMC_RAM_OFFSET;
1078 else if (type == T_FIFO)
1079 base_addr += PMC_FIFO_OFFSET;
1080
1081 mvme_set_dmode(fVMEInterface, MVME_DMODE_D32);
1082
1083 n = 0;
1084 if (size == 1) {
1085 // 8-bit read access
1086 mvme_set_dmode(fVMEInterface, MVME_DMODE_D8);
1087 n = mvme_read(fVMEInterface, static_cast<mvme_locaddr_t*>(data), base_addr + addr, size);
1088 } else if (size == 2) {
1089 // 16-bit read access
1090 mvme_set_dmode(fVMEInterface, MVME_DMODE_D16);
1091 n = mvme_read(fVMEInterface, static_cast<mvme_locaddr_t*>(data), base_addr + addr, size);
1092 } else {
1093 mvme_set_dmode(fVMEInterface, MVME_DMODE_D32);
1094
1095 //mvme_set_blt(fVMEInterface, MVME_BLT_NONE); // Pseudo block transfer
1096 mvme_set_blt(fVMEInterface, MVME_BLT_2EVME); // Use 2eVME if implemented
1097 //mvme_set_blt(fVMEInterface, MVME_BLT_MBLT64); // Use MBLT64 if implemented
1098 //mvme_set_blt(fVMEInterface, MVME_BLT_2ESST); // Use 2eSST if implemented
1099
1100 n = mvme_read(fVMEInterface, static_cast<mvme_locaddr_t*>(data), base_addr + addr, size);
1101 while (n != size) {
1102 printf("Only read %d out of %d, retry with %d: ", n, size, size-n);
1103 i = mvme_read(fVMEInterface, static_cast<mvme_locaddr_t*>(data)+n/4, base_addr + addr + n, size-n);
1104 printf("read %d\n", i);
1105 if (i == 0) {
1106 printf("Error reading VME\n");
1107 return n;
1108 }
1109 n += i;
1110 }
1111
1112 //for (i = 0; i < size; i += 4)
1113 //mvme_read(fVMEInterface, (mvme_locaddr_t *)((char *)data+i), base_addr + addr+i, 4);
1114 }
1115 return n;
1116
1117#endif
1118
1119}
1120
1121
1122/*------------------------------------------------------------------*/
1123
1124#ifdef CT_VME
1125int DRSBoard::AllocateSegmentCMEM(unsigned int SegSize, int *CMEM_SegIdentifier) {
1126
1127 if ((ErrorCode = CMEM_SegmentAllocate(SegSize, "DMA_BUFFER", CMEM_SegIdentifier)) != CMEM_RCC_SUCCESS) {
1128
1129 VME_ErrorString(ErrorCode,ErrorString);
1130
1131 printf("Error: %s\n",ErrorString);
1132 }
1133
1134 return ErrorCode;
1135}
1136#endif
1137
1138/*------------------------------------------------------------------*/
1139
1140#ifdef CT_VME
1141int DRSBoard::AssignPhysicalSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* PCIAddress) {
1142
1143 if ((ErrorCode = CMEM_SegmentPhysicalAddress(CMEM_SegIdentifier, PCIAddress)) != CMEM_RCC_SUCCESS) {
1144
1145 VME_ErrorString(ErrorCode,ErrorString);
1146
1147 printf("Error: %s\n",ErrorString);
1148
1149 }
1150
1151 return ErrorCode;
1152}
1153#endif
1154
1155/*------------------------------------------------------------------*/
1156
1157#ifdef CT_VME
1158int DRSBoard::AssignVirtualSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* VirtualAddress) {
1159
1160 if ((ErrorCode = CMEM_SegmentVirtualAddress(CMEM_SegIdentifier, VirtualAddress)) != CMEM_RCC_SUCCESS) {
1161
1162 VME_ErrorString(ErrorCode,ErrorString);
1163
1164 printf("Error: %s\n",ErrorString);
1165
1166 }
1167
1168 return ErrorCode;
1169}
1170#endif
1171
1172/*------------------------------------------------------------------*/
1173
1174#ifdef CT_VME
1175 int DRSBoard::FreeSegmentCMEM(int CMEM_SegIdentifier) {
1176
1177 // Free memory segment
1178 if ((ErrorCode = CMEM_SegmentFree(CMEM_SegIdentifier)) != CMEM_RCC_SUCCESS) {
1179
1180 VME_ErrorString(ErrorCode,ErrorString);
1181
1182 printf("Error: %s\n",ErrorString);
1183 }
1184
1185 return ErrorCode;
1186 }
1187#endif
1188
1189/*------------------------------------------------------------------*/
1190
1191void DRSBoard::SetLED(int state)
1192{
1193 // Set LED state
1194 if (state)
1195 fCtrlBits |= BIT_LED;
1196 else
1197 fCtrlBits &= ~BIT_LED;
1198 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1199}
1200
1201/*------------------------------------------------------------------*/
1202
1203void DRSBoard::SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels)
1204{
1205 // Set number of channels
1206 unsigned short d;
1207
1208 if (lastChannel < 0 || lastChannel > 10) {
1209 printf("Invalid number of channels: %d (must be between 0 and 10)\n", lastChannel);
1210 return;
1211 }
1212
1213 if (fChipVersion == 2) {
1214 // Register must contain last channel to read out starting from 9
1215 d = 9 - lastChannel;
1216 Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
1217 } else if (fChipVersion == 3) {
1218 // Upper four bits of register must contain last channel to read out starting from 9
1219 d = (firstChannel << 4) | lastChannel;
1220 Write(T_CTRL, REG_CHANNEL_SPAN, &d, 2);
1221
1222 // Set bit pattern for write shift register
1223 switch (nConfigChannels ) {
1224 case 1: d = 0x001; break;
1225 case 2: d = 0x041; break;
1226 case 3: d = 0x111; break;
1227 case 4: d = 0x249; break;
1228 case 6: d = 0x555; break;
1229 case 12: d = 0xFFF; break;
1230 default:
1231 printf("Invalid channel configuration\n");
1232 }
1233 Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
1234 }
1235
1236 fNumberOfReadoutChannels = lastChannel - firstChannel + 1;
1237}
1238
1239/*------------------------------------------------------------------*/
1240
1241void DRSBoard::SetNumberOfChannels(int nChannels)
1242{
1243 SetChannelConfig(0, nChannels-1, 12);
1244}
1245
1246/*------------------------------------------------------------------*/
1247
1248int DRSBoard::SetDAC(unsigned char channel, double value)
1249{
1250 // Set DAC value
1251 unsigned short d;
1252
1253 // Normalize to 2.5V for 16 bit
1254 d = static_cast<unsigned short>(value / 2.5 * 0xFFFF + 0.5);
1255
1256 Write(T_CTRL, REG_DAC_OFS + (channel * 2), &d, 2);
1257 return 1;
1258}
1259
1260/*------------------------------------------------------------------*/
1261
1262int DRSBoard::ReadDAC(unsigned char channel, double *value)
1263{
1264 // Readback DAC value from control register
1265 unsigned char buffer[2];
1266
1267 // Map 0->1, 1->0, 2->3, 3->2, etc.
1268 // ofs = channel + 1 - 2*(channel % 2);
1269
1270 Read(T_CTRL, buffer, REG_DAC_OFS + (channel * 2), 2);
1271
1272 // Normalize to 2.5V for 16 bit
1273 *value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
1274
1275 return 1;
1276}
1277
1278/*------------------------------------------------------------------*/
1279
1280int DRSBoard::GetRegulationDAC(double *value)
1281{
1282 // Get DAC value from status register (-> freq. regulation)
1283 unsigned char buffer[2];
1284
1285 if (fBoardVersion == 1)
1286 Read(T_STATUS, buffer, REG_RDAC3, 2);
1287 else if (fBoardVersion == 2 || fBoardVersion == 3 || fBoardVersion == 4)
1288 Read(T_STATUS, buffer, REG_RDAC1, 2);
1289
1290 // Normalize to 2.5V for 16 bit
1291 *value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
1292
1293 return 1;
1294}
1295
1296/*------------------------------------------------------------------*/
1297
1298int DRSBoard::StartDomino()
1299{
1300 // Start domino sampling
1301 fCtrlBits |= BIT_START_TRIG;
1302 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1303 fCtrlBits &= ~BIT_START_TRIG;
1304
1305 return 1;
1306}
1307
1308/*------------------------------------------------------------------*/
1309
1310int DRSBoard::Reinit()
1311{
1312 // Stop domino sampling
1313 // Reset readout state machine
1314 // Reset FIFO counters
1315 fCtrlBits |= BIT_REINIT_TRIG;
1316 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1317 fCtrlBits &= ~BIT_REINIT_TRIG;
1318
1319 return 1;
1320}
1321
1322/*------------------------------------------------------------------*/
1323
1324int DRSBoard::Init()
1325{
1326 // Reinitialize
1327 fCtrlBits |= BIT_REINIT_TRIG; // Reset readout state machine
1328 fCtrlBits &= ~BIT_FREQ_AUTO_ADJ; // Turn auto. freq regul. off
1329 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1330 fCtrlBits &= ~BIT_REINIT_TRIG;
1331
1332 // Set default DAC voltages
1333
1334 if (fBoardVersion == 1) {
1335 // Set max. domino speed
1336 SetDAC(fDAC_DRA, 2.5);
1337 SetDAC(fDAC_DSA, 2.5);
1338 SetDAC(fDAC_DRB, 2.5);
1339 SetDAC(fDAC_DSB, 2.5);
1340 // Set readout offset
1341 SetDAC(fDAC_COFSA, 0.9);
1342 SetDAC(fDAC_COFSB, 0.9);
1343 SetDAC(fDAC_TLEVEL, 1.7);
1344 } else if (fBoardVersion == 2 || fBoardVersion == 3) {
1345 // Set max. domino speed
1346 SetDAC(fDAC_DSA, 2.5);
1347 SetDAC(fDAC_DSB, 2.5);
1348
1349 // Set readout offset
1350 SetDAC(fDAC_COFS, 0.9);
1351 SetDAC(fDAC_TLEVEL, 1.7);
1352 SetDAC(fDAC_ADCOFS, 1.7); // 1.7 for DC coupling, 1.25 for AC
1353 SetDAC(fDAC_CLKOFS, 1);
1354 } else if (fBoardVersion == 4) {
1355 // Set max. domino speed
1356 SetDAC(fDAC_DSA, 2.5);
1357 SetDAC(fDAC_DSB, 2.5);
1358
1359 // Set readout offset
1360 SetDAC(fDAC_ROFS_1, 1.25); // LVDS level
1361 SetDAC(fDAC_ROFS_2, 0.85); // Linear range 0.1V ... 1.1V
1362
1363 SetDAC(fDAC_ADCOFS, 1.25);
1364 SetDAC(fDAC_ACALIB, 0.5);
1365 SetDAC(fDAC_INOFS, 0.6);
1366 SetDAC(fDAC_BIAS, 0.70); // A bit above the internal bias of 0.68V
1367 }
1368
1369 // Set default number of channels per chip
1370 SetChannelConfig(0, fNumberOfReadoutChannels-1, 12);
1371 SetDominoMode(fDominoMode);
1372 SetReadoutMode(fReadoutMode);
1373 EnableTrigger(fTriggerEnable);
1374
1375 // Disable calibration
1376 EnableAcal(0, 0);
1377 SetCalibTiming(0, 0);
1378
1379 return 1;
1380}
1381
1382/*------------------------------------------------------------------*/
1383
1384int DRSBoard::SetDominoMode(unsigned char mode)
1385{
1386 // Set domino mode
1387 // mode == 0: single sweep
1388 // mode == 1: run continously
1389 //
1390 fDominoMode = mode;
1391 if (mode)
1392 fCtrlBits |= BIT_DMODE;
1393 else
1394 fCtrlBits &= ~BIT_DMODE;
1395
1396 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1397
1398 return 1;
1399}
1400
1401/*------------------------------------------------------------------*/
1402
1403int DRSBoard::SetDominoActive(unsigned char mode)
1404{
1405 // Set domino activity
1406 // mode == 0: stop during readout
1407 // mode == 1: keep domino wave running
1408 //
1409 fDominoMode = mode;
1410 if (mode)
1411 fCtrlBits |= BIT_DACTIVE;
1412 else
1413 fCtrlBits &= ~BIT_DACTIVE;
1414
1415 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1416
1417 return 1;
1418}
1419
1420/*------------------------------------------------------------------*/
1421
1422int DRSBoard::SetReadoutMode(unsigned char mode)
1423{
1424 // Set readout mode
1425 // mode == 0: start from first bin
1426 // mode == 1: start from domino stop
1427 //
1428 fReadoutMode = mode;
1429 if (mode)
1430 fCtrlBits |= BIT_READOUT_MODE;
1431 else
1432 fCtrlBits &= ~BIT_READOUT_MODE;
1433
1434 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1435
1436 return 1;
1437}
1438
1439/*------------------------------------------------------------------*/
1440
1441int DRSBoard::SoftTrigger(void)
1442{
1443 // Send a software trigger
1444 fCtrlBits |= BIT_SOFT_TRIG;
1445 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1446 fCtrlBits &= ~BIT_SOFT_TRIG;
1447
1448 return 1;
1449}
1450
1451/*------------------------------------------------------------------*/
1452
1453int DRSBoard::EnableTrigger(int mode)
1454{
1455 // Enable external trigger
1456 fTriggerEnable = mode;
1457 if (mode)
1458 fCtrlBits |= BIT_ENABLE_TRIGGER;
1459 else
1460 fCtrlBits &= ~BIT_ENABLE_TRIGGER;
1461
1462 if (mode == 2)
1463 fCtrlBits |= BIT_TRIGGER_DELAYED;
1464 else
1465 fCtrlBits &= ~BIT_TRIGGER_DELAYED;
1466
1467 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1468
1469 return 1;
1470}
1471
1472/*------------------------------------------------------------------*/
1473
1474int DRSBoard::SetDelayedStart(int flag)
1475{
1476 // Enable external trigger
1477 fDelayedStart = flag;
1478 if (flag)
1479 fCtrlBits |= BIT_DELAYED_START;
1480 else
1481 fCtrlBits &= ~BIT_DELAYED_START;
1482
1483 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1484
1485 return 1;
1486}
1487
1488/*------------------------------------------------------------------*/
1489
1490int DRSBoard::IsBusy()
1491{
1492 // Get running flag
1493 unsigned int status;
1494
1495 Read(T_STATUS, &status, REG_STATUS, 4);
1496 return (status & BIT_RUNNING) > 0;
1497}
1498
1499/*------------------------------------------------------------------*/
1500
1501int DRSBoard::IsNewFreq(unsigned char chipIndex)
1502{
1503 unsigned int status;
1504
1505 Read(T_STATUS, &status, REG_STATUS, 4);
1506 if (chipIndex == 0)
1507 return (status & BIT_NEW_FREQ1) > 0;
1508 return (status & BIT_NEW_FREQ2) > 0;
1509}
1510
1511/*------------------------------------------------------------------*/
1512
1513int DRSBoard::ReadFrequency(unsigned char chipIndex, double *f)
1514{
1515 // Read domino sampling frequency
1516 unsigned char buffer[2];
1517
1518 if (chipIndex == 0)
1519 Read(T_STATUS, buffer, REG_FREQ1, 2);
1520 else
1521 Read(T_STATUS, buffer, REG_FREQ2, 2);
1522
1523 *f = (static_cast<unsigned int>(buffer[1]) << 8) + buffer[0];
1524
1525 // Convert counts to frequency
1526 if (*f != 0)
1527 *f = 1024 * 200 * (32.768E6 * 4) / (*f) / 1E9;
1528
1529 return 1;
1530}
1531
1532/*------------------------------------------------------------------*/
1533
1534double DRSBoard::VoltToFreq(double volt)
1535{
1536 if (fChipVersion == 3) {
1537 if (volt <= 1.2001)
1538 return (volt - 0.6) / 0.2;
1539 else
1540 return 0.73/0.28 + sqrt((0.73/0.28)*(0.73/0.28)-2.2/0.14+volt/0.14);
1541 } else
1542 return (volt - 0.5) / 0.2;
1543}
1544
1545/*------------------------------------------------------------------*/
1546
1547double DRSBoard::FreqToVolt(double freq)
1548{
1549 if (fChipVersion == 3) {
1550 if (freq <= 3)
1551 return 0.6 + 0.2 * freq;
1552 else
1553 return 2.2 - 0.73 * freq + 0.14 * freq * freq;
1554 } else
1555 return 0.55 + 0.25 * freq;
1556}
1557
1558/*------------------------------------------------------------------*/
1559
1560int DRSBoard::SetFrequency(double demand)
1561{
1562 // Set domino sampling frequency
1563 double freq, voltage, delta_voltage;
1564 unsigned short target;
1565 int i, index, timeout;
1566 int dominoModeSave = fDominoMode;
1567 int triggerEnableSave = fTriggerEnable;
1568
1569 SetDominoMode(1);
1570 EnableTrigger(0);
1571 EnableAcal(0, 0);
1572
1573 fFrequency = demand;
1574
1575 // Turn automatic adjustment off
1576 fCtrlBits &= ~BIT_FREQ_AUTO_ADJ;
1577
1578 // Disable external trigger
1579 fCtrlBits &= ~BIT_ENABLE_TRIGGER;
1580
1581 // Set start pulse length for future DRSBoard_domino_start()
1582 if (fChipVersion == 2) {
1583 if (demand < 0.8)
1584 fCtrlBits |= BIT_LONG_START_PULSE;
1585 else
1586 fCtrlBits &= ~BIT_LONG_START_PULSE;
1587
1588 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1589 }
1590
1591 // Stop any running domino wave
1592 Reinit();
1593
1594 // Estimate DAC setting
1595 voltage = FreqToVolt(demand);
1596
1597 SetDAC(fDAC_DSA, voltage);
1598 SetDAC(fDAC_DSB, voltage);
1599
1600 // Wait until new DAC value has settled
1601 Sleep(10);
1602
1603 // Restart domino wave
1604 StartDomino();
1605
1606 target = static_cast<unsigned short>(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
1607
1608 // Iterate over both DRS chips
1609 for (index = 0; index < 2; index++) {
1610
1611 // Starting voltage
1612 voltage = FreqToVolt(demand);
1613
1614 for (i = 0; i < 100; i++) {
1615
1616 // Wait until measurement finished
1617 for (timeout = 0; timeout < 1000; timeout++)
1618 if (IsNewFreq(index))
1619 break;
1620
1621 freq = 0;
1622 if (timeout == 1000)
1623 break;
1624
1625 ReadFrequency(index, &freq);
1626
1627 delta_voltage = FreqToVolt(demand) - FreqToVolt(freq);
1628
1629 if (fDebug) {
1630 if (fabs(freq - demand) < 0.001)
1631 printf("CHIP #%d, iter%3d: %1.5lf(%05d) %7.5lf\n", index, i, voltage,
1632 static_cast<int>(voltage / 2.5 * 65535 + 0.5), freq);
1633 else
1634 printf("CHIP #%d, iter%3d: %1.5lf(%05d) %7.5lf %+5d\n", index, i, voltage,
1635 static_cast<int>(voltage / 2.5 * 65535 + 0.5), freq,
1636 static_cast<int>(delta_voltage / 2.5 * 65535 + 0.5));
1637 }
1638
1639 if (fabs(freq - demand) < 0.001)
1640 break;
1641
1642 voltage += delta_voltage;
1643 if (voltage > 2.5)
1644 voltage = 2.5;
1645 if (voltage < 0)
1646 voltage = 0;
1647
1648 if (freq == 0)
1649 break;
1650
1651 if (index == 0)
1652 SetDAC(fDAC_DSA, voltage);
1653 else
1654 SetDAC(fDAC_DSB, voltage);
1655
1656 Sleep(10);
1657 }
1658 if (i == 100 || freq == 0 || timeout == 1000) {
1659 printf("Board %d: could not set frequency of CHIP #%d to %1.3f GHz\n", GetCMCSerialNumber(), index, demand);
1660 return 0;
1661 }
1662 }
1663
1664 SetDominoMode(dominoModeSave);
1665 EnableTrigger(triggerEnableSave);
1666 return 1;
1667}
1668
1669/*------------------------------------------------------------------*/
1670
1671int DRSBoard::RegulateFrequency(double demand)
1672{
1673 // Set frequency regulation
1674 unsigned short target, target_hi, target_lo;
1675
1676 if (demand < 0.42 || demand > 5.2)
1677 return 0;
1678
1679 fFrequency = demand;
1680
1681 // First iterate DAC value from host
1682 if (!SetFrequency(demand))
1683 return 0;
1684
1685 // Convert frequency in GHz into counts for 200 cycles
1686 target = static_cast<unsigned short>(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
1687 target_hi = target + 6;
1688 target_lo = target - 6;
1689 Write(T_CTRL, REG_FREQ_SET_HI, &target_hi, 2);
1690 Write(T_CTRL, REG_FREQ_SET_LO, &target_lo, 2);
1691
1692 // Turn on regulation
1693 fCtrlBits |= BIT_FREQ_AUTO_ADJ;
1694 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1695
1696 // Optional monitoring code ...
1697#if 0
1698 do {
1699 double freq;
1700 unsigned short dac, cnt;
1701
1702 ReadFrequency(0, &freq);
1703
1704 if (fBoardVersion == 1)
1705 Read(T_STATUS, &dac, REG_RDAC3, 2);
1706 else if (fBoardVersion == 2 || fBoardVersion == 3)
1707 Read(T_STATUS, &dac, REG_RDAC1, 2);
1708
1709 Read(T_STATUS, &cnt, REG_FREQ1, 2);
1710
1711 if (cnt < 65535)
1712 printf("%5d %5d %5d %1.5lf\n", dac, target, cnt, freq);
1713
1714 Sleep(500);
1715 } while (1);
1716#endif
1717
1718 return 1;
1719}
1720
1721/*------------------------------------------------------------------*/
1722
1723void DRSBoard::RegisterTest()
1724{
1725 // Register test
1726#define N_REG 8
1727
1728 int i, n, n_err;
1729 unsigned int buffer[N_REG], ret[N_REG];
1730
1731 printf("**************************************************\n");
1732
1733 n_err = 0;
1734 for (n = 0; n < 100; n++) {
1735 for (i = 0; i < N_REG; i++)
1736 buffer[i] = (rand() << 16) | rand();
1737 Write(T_CTRL, 0, buffer, sizeof(buffer));
1738
1739 memset(ret, 0, sizeof(ret));
1740 i = Read(T_CTRL, ret, 0, sizeof(ret));
1741
1742 while (i != sizeof(ret)) {
1743 printf(" Read error!\n");
1744 return;
1745 }
1746
1747 for (i = 0; i < N_REG; i++)
1748 if (buffer[i] != ret[i]) {
1749 n_err++;
1750 printf(" Error Reg.%d: %08X - %08X\n", i, buffer[i], ret[i]);
1751 }
1752 else
1753 printf(" OK : %08X\n", buffer[i]);
1754 }
1755
1756 printf(" Register test: %d errors\n", n_err);
1757 printf("**************************************************\n");
1758}
1759
1760/*------------------------------------------------------------------*/
1761
1762int DRSBoard::RAMTest(int flag)
1763{
1764#define N_DWORDS (40*1024/4)
1765
1766 // RAM test
1767 int i, j, n, l=0;
1768 unsigned int buffer[N_DWORDS], ret[N_DWORDS];
1769 time_t now;
1770
1771 // Integrity test
1772 printf("**************************************************\n");
1773 printf(" Integrity:\n");
1774 printf(" Buffer size (bytes): %d (%1.1lfk)\n", static_cast<int>(sizeof(ret)), sizeof(ret) / 1024.0);
1775 if (flag & 1) {
1776 for (i = 0; i < N_DWORDS; i++)
1777 buffer[i] = (rand() | rand() << 16) & 0x00FFFFFF; // Random 24-bit values
1778 //buffer[i] = i;
1779
1780 // Reset FIFO
1781 Reinit();
1782
1783 Write(T_RAM, 0, buffer, sizeof(buffer));
1784 memset(ret, 0, sizeof(ret));
1785
1786 Read(T_FIFO, ret, 0, sizeof(ret));
1787 Reinit();
1788
1789 for (i = n = 0; i < N_DWORDS; i++) {
1790 if (buffer[i] != ret[i])
1791 n++;
1792 }
1793
1794 printf(" %d errors\n", n);
1795 }
1796
1797 // Speed test
1798 if (flag & 2) {
1799
1800 printf(" Speed:\n");
1801
1802 // Read continously to determine speed
1803 time(&now);
1804 while (now == time(NULL));
1805 time(&now);
1806 i = n = 0;
1807 do {
1808 memset(ret, 0, sizeof(ret));
1809
1810 for (j = 0; j < 10; j++) {
1811 Read(T_RAM, ret, 0, sizeof(ret));
1812 i += sizeof(ret);
1813 }
1814
1815 if (flag & 1) {
1816 for (j = 0; j < N_DWORDS; j++)
1817 if (buffer[j] != ret[j])
1818 n++;
1819 }
1820
1821 if (now != time(NULL)) {
1822 if (flag & 1)
1823 printf(" %d read/s, %1.2lf MB/s, %d errors\n", static_cast<int>(i / sizeof(ret)), i / 1024.0 / 1024.0,
1824 n);
1825 else
1826 printf(" %d read/s, %1.2lf MB/s\n", static_cast<int>(i / sizeof(ret)), i / 1024.0 / 1024.0);
1827 time(&now);
1828 i = 0; l++;
1829 }
1830 } while (l<5);
1831 }
1832
1833 printf("**************************************************\n");
1834
1835 return 0;
1836}
1837
1838/*------------------------------------------------------------------*/
1839
1840void DRSBoard::SetVoltageOffset(double offset1, double offset2)
1841{
1842 if (fChipVersion == 3) {
1843 SetDAC(fDAC_ROFS_1, 0.95 - offset1);
1844 SetDAC(fDAC_ROFS_2, 0.95 - offset2);
1845 } else if (fChipVersion == 2)
1846 SetDAC(fDAC_COFS, 0.9 - offset1);
1847}
1848
1849/*------------------------------------------------------------------*/
1850
1851int DRSBoard::SetExternalClockFrequency(double frequencyMHz)
1852{
1853 // Set the frequency of the external clock
1854 fExternalClockFrequency = frequencyMHz;
1855 return 0;
1856}
1857
1858/*------------------------------------------------------------------*/
1859
1860double DRSBoard::GetExternalClockFrequency()
1861{
1862 // Return the frequency of the external clock
1863 return fExternalClockFrequency;
1864}
1865
1866/*------------------------------------------------------------------*/
1867
1868int DRSBoard::TransferWaves(int numberOfChannels)
1869{
1870 return TransferWaves(fWaveforms,numberOfChannels);
1871}
1872
1873/*------------------------------------------------------------------*/
1874
1875int DRSBoard::TransferWaves(unsigned char *p, int numberOfChannels)
1876{
1877 return TransferWaves(p, 0, numberOfChannels-1);
1878}
1879
1880/*------------------------------------------------------------------*/
1881
1882int DRSBoard::TransferWaves(int firstChannel, int lastChannel)
1883{
1884 return TransferWaves(fWaveforms, firstChannel, lastChannel);
1885}
1886
1887/*------------------------------------------------------------------*/
1888
1889int DRSBoard::TransferWaves(unsigned char *p, int firstChannel, int lastChannel)
1890{
1891
1892 // Transfer all waveforms at once
1893 int i, n, offset, n_requested;
1894
1895 if (lastChannel < 0 || lastChannel > kNumberOfChips*kNumberOfChannels) {
1896 printf("Error: Invalid channel index %d\n", lastChannel);
1897 return 0;
1898 }
1899
1900 if (firstChannel < 0 || firstChannel > kNumberOfChips*kNumberOfChannels) {
1901 printf("Error: Invalid channel index %d\n", firstChannel);
1902 return 0;
1903 }
1904
1905 firstChannel = 0;
1906 lastChannel = kNumberOfChips*kNumberOfChannels -1;
1907
1908
1909 n_requested = (lastChannel - firstChannel + 1) * sizeof(short int) * kNumberOfBins;
1910 offset = firstChannel * sizeof(short int) * kNumberOfBins;
1911
1912 n = Read(T_RAM, p, offset, n_requested);
1913
1914 // Fixme (SCC 28082008): this check is now obsolete!!!!
1915 if (n != n_requested) {
1916 printf("Error: only %d bytes read\n", n);
1917 return n;
1918 }
1919
1920 // Remember which waveforms have been transferred
1921 for (i = firstChannel; i <= lastChannel; i++)
1922 fWaveTransferred[i] = true;
1923
1924 //fNumberOfTransferredWaves = numberOfChannels;
1925 return n;
1926}
1927
1928/*------------------------------------------------------------------*/
1929
1930int DRSBoard::TransferWaves(unsigned long *p, int numberOfChannels)
1931{
1932 return TransferWaves(p, 0, numberOfChannels-1);
1933}
1934
1935/*------------------------------------------------------------------*/
1936
1937int DRSBoard::TransferWaves(unsigned long *p, int firstChannel, int lastChannel)
1938{
1939
1940 // Transfer all waveforms at once
1941 int i, n, offset, n_requested;
1942
1943 if (lastChannel < 0 || lastChannel > kNumberOfChips*kNumberOfChannels) {
1944 printf("Error: Invalid channel index %d\n", lastChannel);
1945 return 0;
1946 }
1947
1948 if (firstChannel < 0 || firstChannel > kNumberOfChips*kNumberOfChannels) {
1949 printf("Error: Invalid channel index %d\n", firstChannel);
1950 return 0;
1951 }
1952
1953 firstChannel = 0;
1954 lastChannel = kNumberOfChips*kNumberOfChannels - 1;
1955
1956
1957 n_requested = (lastChannel - firstChannel + 1) * sizeof(short int) * kNumberOfBins;
1958 offset = firstChannel * sizeof(short int) * kNumberOfBins;
1959
1960 n = Read(T_RAM, p, offset, n_requested);
1961
1962 if (n != n_requested) {
1963 printf("Error: only %d bytes read\n", n);
1964 return n;
1965 }
1966
1967 // Remember which waveforms have been transferred
1968 for (i = firstChannel; i <= lastChannel; i++)
1969 fWaveTransferred[i] = true;
1970
1971 //fNumberOfTransferredWaves = numberOfChannels;
1972 return n;
1973}
1974
1975/*------------------------------------------------------------------*/
1976
1977int DRSBoard::DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
1978{
1979
1980 return DecodeWave(fWaveforms , chipIndex, channel, waveform);
1981}
1982
1983/*------------------------------------------------------------------*/
1984
1985int DRSBoard::DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
1986{
1987
1988 // Get waveform
1989 int i, offset, ind;
1990
1991 // Check valid parameters
1992 if (channel > 9 || chipIndex > 1)
1993 return kWrongChannelOrChip;
1994
1995 // Re-map channel
1996 if (fBoardVersion == 1) {
1997 if (channel < 8)
1998 channel = 7 - channel;
1999 else
2000 channel = 16 - channel;
2001 } else {
2002 channel = channel;
2003 }
2004
2005 offset = (kNumberOfBins * 4) * channel;
2006
2007 if (DEBUG)
2008 printf("offset = %d (0X%X)\n",offset,offset);
2009
2010 for (i = 0; i < kNumberOfBins; i++) {
2011
2012 ind = i * 4 + offset;
2013
2014 if (chipIndex == 0)
2015 // Lower 12 bit
2016 waveform[i] = ((waveforms[ind + 1] & 0x0f) << 8) | waveforms[ind];
2017 else
2018 // Upper 12 bit
2019 waveform[i] = (waveforms[ind + 2] << 4) | (waveforms[ind + 1] >> 4);
2020 }
2021
2022 return kSuccess;
2023}
2024
2025/*------------------------------------------------------------------*/
2026
2027int DRSBoard::DecodeWave(unsigned long *waveforms, unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
2028{
2029
2030 // Get waveform
2031 int i, offset, ind;
2032
2033 // Check valid parameters
2034 if (channel > 9 || chipIndex > 1)
2035 return kWrongChannelOrChip;
2036
2037 // Re-map channel
2038 if (fBoardVersion == 1) {
2039 if (channel < 8)
2040 channel = 7 - channel;
2041 else
2042 channel = 16 - channel;
2043 } else {
2044 channel = channel;
2045 }
2046
2047 offset = kNumberOfBins * channel;
2048
2049 for (i = 0; i < kNumberOfBins; i++) {
2050
2051 ind = i + offset;
2052
2053 // Lower 12 bit
2054 if (chipIndex == 0)
2055 waveform[i] = (unsigned short)(waveforms[ind] & 0X00000FFF);
2056 // Upper 12 bit
2057 else
2058 waveform[i] = (unsigned short)(((unsigned long)(waveforms[ind] & 0X00FFF000)) >> 12);
2059 }
2060
2061 return kSuccess;
2062}
2063
2064/*------------------------------------------------------------------*/
2065
2066int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
2067 int triggerCell, bool adjustToClock, float threshold)
2068{
2069
2070 int ret;
2071
2072 ret = GetWave(fWaveforms,chipIndex,channel,waveform,responseCalib,triggerCell,adjustToClock,threshold);
2073
2074 if (kRotateWave) RotateWave((int)GetTriggerCell(chipIndex),waveform);
2075
2076 return ret;
2077}
2078
2079/*------------------------------------------------------------------*/
2080
2081int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
2082 int triggerCell, bool adjustToClock, float threshold)
2083{
2084 int ret,i;
2085 short waveS[kNumberOfBins];
2086
2087 ret = GetWave(fWaveforms,chipIndex,channel,waveS,responseCalib,triggerCell,adjustToClock,threshold);
2088
2089 if (responseCalib)
2090 for (i = 0; i < kNumberOfBins; i++)
2091 waveform[i] = static_cast<float>(waveS[i] * GetPrecision());
2092 else {
2093 for (i = 0; i < kNumberOfBins; i++) {
2094 if (fBoardVersion==4)
2095 waveform[i] = static_cast<float>(waveS[i] / 4.095); // 12-bit corresponding to 1V
2096 else
2097 waveform[i] = static_cast<float>(waveS[i]);
2098 }
2099 }
2100
2101 if (kRotateWave)
2102 //RotateWave((int)GetTriggerCell(waveform,chipIndex),waveform);
2103 RotateWave((int)GetTriggerCell(chipIndex),waveform);
2104
2105 return ret;
2106}
2107
2108/*------------------------------------------------------------------*/
2109
2110void DRSBoard::RotateWave(int triggerCell, float *waveform)
2111{
2112 int i;
2113 float buffer[kNumberOfBins];
2114
2115 memcpy((float*)buffer,(float*)waveform,sizeof(buffer));
2116
2117 for (i=0;i<kNumberOfBins;i++)
2118 waveform[i] = buffer[(i + triggerCell)%kNumberOfBins];
2119}
2120
2121/*------------------------------------------------------------------*/
2122
2123void DRSBoard::RotateWave(int triggerCell, short *waveform)
2124{
2125 int i;
2126 short buffer[kNumberOfBins];
2127
2128 memcpy((short*)buffer,(short*)waveform,sizeof(buffer));
2129
2130 for (i=0;i<kNumberOfBins;i++)
2131 waveform[i] = buffer[(i + triggerCell)%kNumberOfBins];
2132}
2133
2134/*------------------------------------------------------------------*/
2135
2136
2137int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
2138 int triggerCell, bool adjustToClock, float threshold)
2139{
2140 int ret,i;
2141 short waveS[kNumberOfBins];
2142
2143 ret = GetWave(waveforms,chipIndex,channel,waveS,responseCalib,triggerCell,adjustToClock,threshold);
2144
2145 if (responseCalib)
2146 for (i = 0; i < kNumberOfBins; i++)
2147 waveform[i] = static_cast<float>(waveS[i] * GetPrecision());
2148 else {
2149 for (i = 0; i < kNumberOfBins; i++) {
2150 if (fBoardVersion == 4)
2151 waveform[i] = static_cast<float>(waveS[i] / 4.095); // 12-bit corresponding to 1V
2152 else
2153 waveform[i] = static_cast<float>(waveS[i]);
2154 }
2155 }
2156 return ret;
2157}
2158
2159/*------------------------------------------------------------------*/
2160
2161
2162int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
2163 int triggerCell, bool adjustToClock, float threshold)
2164{
2165 if (!fWaveTransferred[chipIndex*kNumberOfChannels+channel])
2166 return kWaveNotAvailable;
2167 unsigned short adcWaveform[kNumberOfBins];
2168 int ret = DecodeWave(waveforms, chipIndex, channel, adcWaveform);
2169 if (ret!=kSuccess)
2170 return ret;
2171
2172 return CalibrateWaveform(chipIndex, channel, adcWaveform, waveform, responseCalib,
2173 triggerCell, adjustToClock, threshold);
2174}
2175
2176/*------------------------------------------------------------------*/
2177
2178int DRSBoard::GetWave(unsigned long *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
2179 int triggerCell, bool adjustToClock, float threshold)
2180{
2181 if (!fWaveTransferred[chipIndex*kNumberOfChannels+channel])
2182 return kWaveNotAvailable;
2183 unsigned short adcWaveform[kNumberOfBins];
2184 int ret = DecodeWave(waveforms, chipIndex, channel, adcWaveform);
2185 if (ret!=kSuccess)
2186 return ret;
2187
2188 return CalibrateWaveform(chipIndex, channel, adcWaveform, waveform, responseCalib,
2189 triggerCell, adjustToClock, threshold);
2190}
2191
2192/*------------------------------------------------------------------*/
2193
2194int DRSBoard::GetADCWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
2195{
2196 return DecodeWave(chipIndex, channel, waveform);
2197}
2198
2199/*------------------------------------------------------------------*/
2200
2201int DRSBoard::GetADCWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
2202{
2203 return DecodeWave(waveforms, chipIndex, channel, waveform);
2204}
2205
2206/*------------------------------------------------------------------*/
2207
2208int DRSBoard::GetADCWave(unsigned long *waveforms,unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
2209{
2210 return DecodeWave(waveforms, chipIndex, channel, waveform);
2211}
2212
2213/*------------------------------------------------------------------*/
2214
2215int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
2216 short *waveform, bool responseCalib,
2217 int triggerCell, bool // adjustToClock
2218 , float threshold)
2219{
2220 int j;
2221
2222 // Calibrate waveform
2223 if (responseCalib) {
2224 if (!fResponseCalibration->Calibrate(chipIndex, channel % 10, adcWaveform, waveform, triggerCell, threshold))
2225 return kZeroSuppression; // Return immediately if below threshold
2226 } else {
2227 for (j = 0; j < kNumberOfBins; j++) {
2228 waveform[j] = adcWaveform[j];
2229 }
2230 }
2231 // Fix bad cells for single turn mode
2232 if (fDominoMode == 0 && triggerCell==-1) {
2233 waveform[0] = 2 * waveform[1] - waveform[2];
2234 short m1 = (waveform[kNumberOfBins - 5] + waveform[kNumberOfBins - 6]) / 2;
2235 short m2 = (waveform[kNumberOfBins - 6] + waveform[kNumberOfBins - 7]) / 2;
2236 waveform[kNumberOfBins - 4] = m1 - 1 * (m2 - m1);
2237 waveform[kNumberOfBins - 3] = m1 - 2 * (m2 - m1);
2238 waveform[kNumberOfBins - 2] = m1 - 3 * (m2 - m1);
2239 waveform[kNumberOfBins - 1] = m1 - 4 * (m2 - m1);
2240 }
2241 return kSuccess;
2242}
2243
2244/*------------------------------------------------------------------*/
2245
2246int DRSBoard::GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period)
2247{
2248 int j;
2249 if (*time >= measurement[numberOfMeasurements - 1]) {
2250 *time -= measurement[numberOfMeasurements - 1];
2251 return 1;
2252 }
2253 if (*time < measurement[0]) {
2254 *time = *time - measurement[0] - (numberOfMeasurements - 1) * period / 2;
2255 return 1;
2256 }
2257 for (j = 0; j < numberOfMeasurements - 1; j++) {
2258 if (*time > measurement[j] && *time <= measurement[j + 1]) {
2259 *time =
2260 (period / 2) / (measurement[j + 1] - measurement[j]) * (*time - measurement[j + 1]) -
2261 (numberOfMeasurements - 2 - j) * period / 2;
2262 return 1;
2263 }
2264 }
2265 return 0;
2266}
2267
2268/*------------------------------------------------------------------*/
2269
2270int DRSBoard::GetTriggerCell(unsigned int chipIndex)
2271{
2272
2273 return GetTriggerCell(fWaveforms,chipIndex);
2274}
2275
2276/*------------------------------------------------------------------*/
2277
2278int DRSBoard::GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex)
2279{
2280
2281 int j, triggerCell;
2282 bool calib = 0;
2283 unsigned short baseLevel = 1000;
2284 unsigned short triggerChannel[1024];
2285 if (!fWaveTransferred[chipIndex*kNumberOfChannels+8])
2286 return -1;
2287
2288 GetADCWave(waveforms,chipIndex, 8, triggerChannel);
2289 //calib = fResponseCalibration->SubtractADCOffset(chipIndex, 8, triggerChannel, triggerChannel,baseLevel); // Changed 24/10/2008, SCC
2290
2291
2292 triggerCell = -1;
2293 for (j = 0; j < kNumberOfBins; j++) {
2294 if (calib) {
2295 if (triggerChannel[j] <= baseLevel+200
2296 && triggerChannel[(j + 1) % kNumberOfBins] > baseLevel+200) {
2297 triggerCell = j;
2298 break;
2299 }
2300 } else {
2301 if (triggerChannel[j] >= 2000
2302 && triggerChannel[(j + 1) % kNumberOfBins] < 2000) {
2303 triggerCell = j;
2304 break;
2305 }
2306 }
2307 }
2308 if (triggerCell == -1) {
2309 return kInvalidTriggerSignal;
2310 }
2311 fTriggerCell = triggerCell;
2312 return triggerCell;
2313}
2314
2315/*------------------------------------------------------------------*/
2316
2317
2318int DRSBoard::GetTriggerCell(unsigned long *waveforms,unsigned int chipIndex)
2319{
2320
2321 int j, triggerCell;
2322 bool calib = 0;
2323 unsigned short baseLevel = 1000;
2324 unsigned short triggerChannel[1024];
2325 if (!fWaveTransferred[chipIndex*kNumberOfChannels+8])
2326 return -1;
2327
2328 GetADCWave(waveforms,chipIndex, 8, triggerChannel);
2329 //calib = fResponseCalibration->SubtractADCOffset(chipIndex, 8, triggerChannel, triggerChannel, baseLevel); // Changed 07/10/2008, SCC
2330
2331 triggerCell = -1;
2332 for (j = 0; j < kNumberOfBins; j++) {
2333 if (calib) {
2334
2335 if (triggerChannel[j] <= baseLevel+200
2336 && triggerChannel[(j + 1) % kNumberOfBins] > baseLevel+200) {
2337 triggerCell = j;
2338 break;
2339 }
2340 } else {
2341
2342 if (triggerChannel[j] >= 2000
2343 && triggerChannel[(j + 1) % kNumberOfBins] < 2000) {
2344 triggerCell = j;
2345 break;
2346 }
2347 }
2348 }
2349
2350 if (triggerCell == -1) {
2351 return kInvalidTriggerSignal;
2352 }
2353 fTriggerCell = triggerCell;
2354 return triggerCell;
2355
2356}
2357
2358/*------------------------------------------------------------------*/
2359
2360int DRSBoard::GetTriggerCell(float *waveform)
2361{
2362 int j, triggerCell;
2363
2364 triggerCell = -1;
2365
2366 for (j = 0; j < kNumberOfBins; j++)
2367 if ((waveform[(j + 1) % kNumberOfBins]-waveform[j % kNumberOfBins]) > 400.)
2368 triggerCell = j;
2369
2370
2371 if (triggerCell == -1) {
2372 return kInvalidTriggerSignal;
2373 }
2374 fTriggerCell = triggerCell;
2375 return triggerCell;
2376
2377}
2378
2379/*------------------------------------------------------------------*/
2380
2381void DRSBoard::TestDAC(int channel)
2382{
2383 // Test DAC
2384 int status;
2385
2386 do {
2387 status = SetDAC(channel, 0);
2388 Sleep(1000);
2389 status = SetDAC(channel, 0.5);
2390 Sleep(1000);
2391 status = SetDAC(channel, 1);
2392 Sleep(1000);
2393 status = SetDAC(channel, 1.5);
2394 Sleep(1000);
2395 status = SetDAC(channel, 2);
2396 Sleep(1000);
2397 status = SetDAC(channel, 2.5);
2398 Sleep(1000);
2399 } while (status);
2400}
2401
2402/*------------------------------------------------------------------*/
2403
2404void DRSBoard::MeasureSpeed()
2405{
2406 // Measure domino sampling speed
2407 FILE *f;
2408 double vdr, vds, freq;
2409
2410 f = fopen("speed.txt", "wt");
2411 fprintf(f, "\t");
2412 printf("\t");
2413 for (vdr = 0.5; vdr <= 2.501; vdr += 0.05) {
2414 fprintf(f, "%1.2lf\t", vdr);
2415 printf("%1.2lf\t", vdr);
2416 }
2417 fprintf(f, "\n");
2418 printf("\n");
2419
2420 for (vds = 0.5; vds <= 2.501; vds += 0.05) {
2421 fprintf(f, "%1.2lf\t", vds);
2422 printf("%1.2lf\t", vds);
2423
2424 SetDAC(fDAC_DSA, vds);
2425 StartDomino();
2426 Sleep(1000);
2427 ReadFrequency(0, &freq);
2428
2429 fprintf(f, "%1.3lf\t", freq);
2430 printf("%1.3lf\t", freq);
2431
2432 fprintf(f, "\n");
2433 printf("\n");
2434 fflush(f);
2435 }
2436}
2437
2438/*------------------------------------------------------------------*/
2439
2440void DRSBoard::InteractSpeed()
2441{
2442 int status, i;
2443 double freq, vds;
2444
2445 do {
2446 printf("DS: ");
2447 scanf("%lf", &vds);
2448 if (vds == 0)
2449 break;
2450
2451 SetDAC(fDAC_DSA, vds);
2452 SetDAC(fDAC_DSB, vds);
2453
2454 StartDomino();
2455 for (i = 0; i < 4; i++) {
2456 Sleep(1000);
2457
2458 status = ReadFrequency(0, &freq);
2459 if (!status)
2460 break;
2461 printf("%1.6lf GHz\n", freq);
2462 }
2463
2464 // Turn CMC_LED off
2465 SetLED(0);
2466
2467 } while (1);
2468}
2469
2470/*------------------------------------------------------------------*/
2471
2472void DRSBoard::MonitorFrequency()
2473{
2474 // Monitor domino sampling frequency
2475 int status;
2476 unsigned int data;
2477 double freq, dac;
2478 FILE *f;
2479 time_t now;
2480 char str[256];
2481
2482 f = fopen("DRSBoard.log", "w");
2483
2484 do {
2485 Sleep(1000);
2486
2487 status = ReadFrequency(0, &freq);
2488 if (!status)
2489 break;
2490
2491 data = 0;
2492 if (fBoardVersion == 1)
2493 Read(T_STATUS, &data, REG_RDAC3, 2);
2494 else if (fBoardVersion == 2 || fBoardVersion == 3)
2495 Read(T_STATUS, &data, REG_RDAC1, 2);
2496
2497 dac = data / 65536.0 * 2.5;
2498 printf("%1.6lf GHz, %1.4lf V\n", freq, dac);
2499 time(&now);
2500 strcpy(str, ctime(&now) + 11);
2501 str[8] = 0;
2502
2503 fprintf(f, "%s %1.6lf GHz, %1.4lf V\n", str, freq, dac);
2504 fflush(f);
2505
2506 } while (!drs_kbhit());
2507
2508 fclose(f);
2509}
2510
2511/*------------------------------------------------------------------*/
2512
2513unsigned int DRSBoard::GetCtrlReg()
2514{
2515 unsigned int status;
2516
2517 Read(T_CTRL, &status, REG_CTRL, 4);
2518 return status;
2519}
2520
2521/*------------------------------------------------------------------*/
2522
2523unsigned int DRSBoard::GetStatusReg()
2524{
2525 unsigned int status;
2526
2527 Read(T_STATUS, &status, REG_STATUS, 4);
2528 return status;
2529}
2530
2531/*------------------------------------------------------------------*/
2532
2533int DRSBoard::EnableTcal(int flag)
2534{
2535 // Enable clock channel
2536 if (flag)
2537 fCtrlBits |= BIT_TCAL_EN;
2538 else
2539 fCtrlBits &= ~BIT_TCAL_EN;
2540
2541 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2542
2543 return 1;
2544}
2545
2546/*------------------------------------------------------------------*/
2547
2548int DRSBoard::EnableAcal(int mode, double voltage)
2549{
2550 double t1, t2;
2551
2552 if (mode == 0) {
2553 // Turn calibration off
2554 SetCalibTiming(0, 0);
2555 fCtrlBits &= ~BIT_ACAL_EN;
2556 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2557 } else if (mode == 1) {
2558 // Static calibration
2559 SetCalibVoltage(voltage);
2560 SetCalibTiming(0, 0);
2561 fCtrlBits |= BIT_ACAL_EN;
2562 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2563 } else if (mode == 2) {
2564 // First part calibration:
2565 // stop domino wave after 1.2 revolutions,
2566 // turn on calibration voltage after 0.1 revolutions
2567
2568 // Ensure circulating domino wave
2569 SetDominoMode(1);
2570
2571 // Set calibration voltage but do not turn it on now
2572 SetCalibVoltage(voltage);
2573 fCtrlBits &= ~BIT_ACAL_EN;
2574 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2575
2576 // Calculate duration of DENABLE signal as 1.2 revolutions
2577 t1 = 1 / fFrequency * 1024 * 1.2; // ns
2578 t1 = static_cast<int>((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
2579 t2 = 1 / fFrequency * 1024 * 0.1; // ns
2580 t2 = static_cast<int>((t2 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
2581 SetCalibTiming(static_cast<int>(t1), static_cast<int>(t2));
2582
2583 } else if (mode == 3) {
2584 // Second part calibration:
2585 // stop domino wave after 1.05 revolutions
2586
2587 // Ensure circulating domino wave
2588 SetDominoMode(1);
2589
2590 // Turn on and let settle calibration voltage
2591 SetCalibVoltage(voltage);
2592 fCtrlBits |= BIT_ACAL_EN;
2593 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2594
2595 // Calculate duration of DENABLE signal as 1.1 revolutions
2596 t1 = 1 / fFrequency * 1024 * 1.05; // ns
2597 t1 = static_cast<int>((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
2598 SetCalibTiming(static_cast<int>(t1), 0);
2599 }
2600
2601 return 1;
2602}
2603
2604/*------------------------------------------------------------------*/
2605
2606int DRSBoard::SetCalibTiming(int t_enable, int t_cal)
2607{
2608 unsigned short d;
2609
2610 if (fChipVersion == 2) {
2611 d = t_cal | (t_enable << 8);
2612 Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
2613 }
2614
2615 if (fChipVersion == 3) {
2616 d = t_cal;
2617 Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
2618 }
2619
2620 return 1;
2621}
2622
2623/*------------------------------------------------------------------*/
2624
2625int DRSBoard::SetCalibVoltage(double value)
2626{
2627 // Set Calibration Voltage
2628 SetDAC(fDAC_ACALIB, value);
2629 return 1;
2630}
2631
2632/*------------------------------------------------------------------*/
2633
2634double DRSBoard::GetTemperature()
2635{
2636 // Read Out Temperature Sensor
2637 unsigned char buffer[2];
2638 unsigned short d;
2639 double temperature;
2640
2641 Read(T_STATUS, buffer, REG_TEMPERATURE, 2);
2642
2643 d = (static_cast<unsigned int>(buffer[1]) << 8) + buffer[0];
2644 temperature = ((d >> 3) & 0x0FFF) * 0.0625;
2645
2646 return temperature;
2647}
2648
2649/*------------------------------------------------------------------*/
2650
2651int DRSBoard::GetTriggerBus()
2652{
2653 unsigned short status;
2654
2655 Read(T_STATUS, &status, REG_TRIGGER_BUS, 2);
2656 return static_cast<int>(status);
2657}
2658
2659/*------------------------------------------------------------------*/
2660
2661int DRSBoard::FlashEEPROM(unsigned short serial_cmc)
2662{
2663 unsigned short dac;
2664
2665 // Read current DAC register
2666 Read(T_CTRL, &dac, REG_DAC0, 2);
2667
2668 // Put serial in DAC register
2669 Write(T_CTRL, REG_DAC0, &serial_cmc, 2);
2670
2671 // Execute flash
2672 fCtrlBits |= BIT_FLASH_TRIG;
2673 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2674 fCtrlBits &= ~BIT_FLASH_TRIG;
2675
2676 // Wait 6 ms per word
2677 Sleep(20);
2678
2679 // Write back old DAC registers
2680 Write(T_CTRL, REG_DAC0, &dac, 2);
2681
2682 // Read back serial number
2683 ReadSerialNumber();
2684
2685 return 1;
2686}
2687
2688/*------------------------------------------------------------------*/
2689
2690int DRSBoard::GetTime(unsigned int chipIndex, int frequencyMHz, float *time,int triggerCell)
2691{
2692 int i,irot;
2693 DRSBoard::TimeData * init;
2694 DRSBoard::TimeData::FrequencyData * freq;
2695
2696 init = GetTimeCalibration(chipIndex);
2697
2698 if (init == NULL) {
2699 for (i = 0; i < kNumberOfBins; i++)
2700 time[i] = static_cast<float>(i / fFrequency);
2701 return 1;
2702 }
2703 freq = NULL;
2704 for (i = 0; i < init->fNumberOfFrequencies; i++) {
2705 if (init->fFrequency[i]->fFrequency == frequencyMHz) {
2706 freq = init->fFrequency[i];
2707 break;
2708 }
2709 }
2710 if (freq == NULL) {
2711 for (i = 0; i < kNumberOfBins; i++)
2712 time[i] = static_cast<float>(i / fFrequency);
2713 return 1;
2714 }
2715 for (i = 0; i < kNumberOfBins; i++) {
2716 irot = i;
2717 if (triggerCell>-1)
2718 irot = (triggerCell + i) % kNumberOfBins;
2719 if (triggerCell + i < kNumberOfBins)
2720 time[i] = static_cast<float>((freq->fBin[irot] - freq->fBin[triggerCell]) / fFrequency);
2721 else
2722 time[i] = static_cast<float>((freq->fBin[irot] - freq->fBin[triggerCell] + freq->fBin[kNumberOfBins - 1] -
2723 2 * freq->fBin[0] + freq->fBin[1]) / fFrequency);
2724 }
2725 return 1;
2726}
2727
2728/*------------------------------------------------------------------*/
2729
2730bool DRSBoard::InitTimeCalibration(unsigned int chipIndex)
2731{
2732 return GetTimeCalibration(chipIndex, true) != NULL;
2733}
2734
2735/*------------------------------------------------------------------*/
2736
2737DRSBoard::TimeData *DRSBoard::GetTimeCalibration(unsigned int chipIndex, bool reinit)
2738{
2739 int i, l, index;
2740 char *cstop;
2741 char fileName[500];
2742 char error[240];
2743 PMXML_NODE node, rootNode, mainNode;
2744
2745 index = fNumberOfTimeData;
2746 for (i = 0; i < fNumberOfTimeData; i++) {
2747 if (fTimeData[i]->fChip == static_cast < int >(chipIndex)) {
2748 if (!reinit)
2749 return fTimeData[i];
2750 else {
2751 index = i;
2752 break;
2753 }
2754 }
2755 }
2756
2757 fTimeData[index] = new DRSBoard::TimeData();
2758 DRSBoard::TimeData * init = fTimeData[index];
2759
2760 init->fChip = chipIndex;
2761
2762 for (i = 0; i < init->kMaxNumberOfFrequencies; i++) {
2763 if (i <= 499 || (i >= 501 && i <= 999) || (i >= 1001 && i <= 1499) || (i >= 1501 && i <= 1999) || (i >= 2001 && i <= 2499) || i >= 2501)
2764 continue;
2765 sprintf(fileName, "%s/board%d/TimeCalib_board%d_chip%d_%dMHz.xml", fCalibDirectory, fCMCSerialNumber,
2766 fCMCSerialNumber, chipIndex, i);
2767 rootNode = mxml_parse_file(fileName, error, sizeof(error));
2768 if (rootNode == NULL)
2769 continue;
2770
2771 init->fFrequency[init->fNumberOfFrequencies] = new DRSBoard::TimeData::FrequencyData();
2772 init->fFrequency[init->fNumberOfFrequencies]->fFrequency = i;
2773
2774 mainNode = mxml_find_node(rootNode, "/DRSTimeCalibration");
2775
2776 for (l = 0; l < kNumberOfBins; l++) {
2777 node = mxml_subnode(mainNode, l + 2);
2778 init->fFrequency[init->fNumberOfFrequencies]->fBin[l] = strtod(mxml_get_value(node), &cstop);
2779 }
2780 mxml_free_tree(rootNode);
2781 init->fNumberOfFrequencies++;
2782 }
2783 if (init->fNumberOfFrequencies == 0) {
2784 printf("Board %d --> Could not find time calibration file\n", GetCMCSerialNumber());
2785 }
2786
2787 if (index == fNumberOfTimeData)
2788 fNumberOfTimeData++;
2789
2790 return fTimeData[index];
2791}
2792
2793/*------------------------------------------------------------------*/
2794
2795void DRSBoard::SetCalibrationDirectory(const char *calibrationDirectoryPath)
2796{
2797 strncpy(fCalibDirectory, calibrationDirectoryPath, strlen(calibrationDirectoryPath));
2798 fCalibDirectory[strlen(calibrationDirectoryPath)] = 0;
2799};
2800
2801/*------------------------------------------------------------------*/
2802
2803void DRSBoard::GetCalibrationDirectory(char *calibrationDirectoryPath)
2804{
2805 strncpy(calibrationDirectoryPath, fCalibDirectory, strlen(fCalibDirectory));
2806 calibrationDirectoryPath[strlen(fCalibDirectory)] = 0;
2807};
2808
2809/*------------------------------------------------------------------*/
2810
2811void DRSBoard::LinearRegression(double *x, double *y, int n, double *a, double *b)
2812{
2813 int i;
2814 double sx, sxx, sy, sxy;
2815
2816 sx = sxx = sy = sxy = 0;
2817 for (i = 0; i < n; i++) {
2818 sx += x[i];
2819 sxx += x[i] * x[i];
2820 sy += y[i];
2821 sxy += x[i] * y[i];
2822 }
2823
2824 *a = (n * sxy - sx*sy) / (n * sxx - sx * sx);
2825 *b = (sy - *a * sx) / n;
2826}
2827
2828/*------------------------------------------------------------------*/
2829
2830void ResponseCalibration::SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints,
2831 int numberOfMode2Bins, int numberOfSamples,
2832 int numberOfGridPoints, int numberOfXConstPoints,
2833 int numberOfXConstGridPoints, double triggerFrequency,
2834 int showStatistics)
2835{
2836 DeleteFields();
2837 InitFields(numberOfPointsLowVolt, numberOfPoints, numberOfMode2Bins, numberOfSamples, numberOfGridPoints,
2838 numberOfXConstPoints, numberOfXConstGridPoints, triggerFrequency, showStatistics);
2839}
2840
2841/*------------------------------------------------------------------*/
2842
2843void ResponseCalibration::ResetCalibration()
2844{
2845 int i;
2846 for (i = 0; i < kNumberOfChips; i++)
2847 fCalibrationData[i]->fRead = false;
2848 fCurrentPoint = 0;
2849 fCurrentLowVoltPoint = 0;
2850 fCurrentSample = 0;
2851 fCurrentFitChannel = 0;
2852 fCurrentFitBin = 0;
2853 fRecorded = false;
2854 fFitted = false;
2855 fOffset = false;
2856};
2857
2858/*------------------------------------------------------------------*/
2859
2860bool ResponseCalibration::WriteCalibration(unsigned int chipIndex)
2861{
2862 if (!fOffset)
2863 return false;
2864 if (fBoard->GetChipVersion() == 3)
2865 return WriteCalibrationV4(chipIndex);
2866 else
2867 return WriteCalibrationV3(chipIndex);
2868}
2869
2870/*------------------------------------------------------------------*/
2871
2872bool ResponseCalibration::WriteCalibrationV3(unsigned int chipIndex)
2873{
2874 if (!fOffset)
2875 return false;
2876
2877 int ii, j, k;
2878 char str[1000];
2879 char strt[1000];
2880 short tempShort;
2881 CalibrationData *data = fCalibrationData[chipIndex];
2882 CalibrationData::CalibrationDataChannel * chn;
2883
2884 // Open File
2885 fBoard->GetCalibrationDirectory(strt);
2886 sprintf(str, "%s/board%d", strt, fBoard->GetCMCSerialNumber());
2887 if (MakeDir(str) == -1) {
2888 printf("Error: Cannot create directory \"%s\"\n", str);
2889 return false;
2890 }
2891 sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetCMCSerialNumber(),
2892 fBoard->GetCMCSerialNumber(), chipIndex, static_cast<int>(fBoard->GetFrequency() * 1000));
2893 fCalibFile = fopen(str, "wb");
2894 if (fCalibFile == NULL) {
2895 printf("Error: Cannot write to file \"%s\"\n", str);
2896 return false;
2897 }
2898 // Write File
2899 fwrite(&data->fNumberOfGridPoints, 1, 1, fCalibFile);
2900 tempShort = static_cast<short>(data->fStartTemperature) * 10;
2901 fwrite(&tempShort, 2, 1, fCalibFile);
2902 tempShort = static_cast<short>(data->fEndTemperature) * 10;
2903 fwrite(&tempShort, 2, 1, fCalibFile);
2904 fwrite(&data->fMin, 4, 1, fCalibFile);
2905 fwrite(&data->fMax, 4, 1, fCalibFile);
2906 fwrite(&data->fNumberOfLimitGroups, 1, 1, fCalibFile);
2907
2908 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
2909 chn = data->fChannel[ii];
2910 for (j = 0; j < kNumberOfBins; j++) {
2911 fwrite(&chn->fLimitGroup[j], 1, 1, fCalibFile);
2912 fwrite(&chn->fLookUpOffset[j], 2, 1, fCalibFile);
2913 fwrite(&chn->fNumberOfLookUpPoints[j], 1, 1, fCalibFile);
2914 for (k = 0; k < chn->fNumberOfLookUpPoints[j]; k++) {
2915 fwrite(&chn->fLookUp[j][k], 1, 1, fCalibFile);
2916 }
2917 for (k = 0; k < data->fNumberOfGridPoints; k++) {
2918 fwrite(&chn->fData[j][k], 2, 1, fCalibFile);
2919 }
2920 fwrite(&chn->fOffsetADC[j], 2, 1, fCalibFile);
2921 fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
2922 }
2923 }
2924 fclose(fCalibFile);
2925
2926 printf("Calibration successfully written to\n\"%s\"\n", str);
2927 return true;
2928}
2929
2930/*------------------------------------------------------------------*/
2931
2932bool ResponseCalibration::WriteCalibrationV4(unsigned int chipIndex)
2933{
2934 if (!fOffset)
2935 return false;
2936
2937 int ii, j;
2938 char str[1000];
2939 char strt[1000];
2940 CalibrationData *data = fCalibrationData[chipIndex];
2941 CalibrationData::CalibrationDataChannel * chn;
2942
2943 // Open File
2944 fBoard->GetCalibrationDirectory(strt);
2945 sprintf(str, "%s/board%d", strt, fBoard->GetCMCSerialNumber());
2946 if (MakeDir(str) == -1) {
2947 printf("Error: Cannot create directory \"%s\"\n", str);
2948 return false;
2949 }
2950 sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetCMCSerialNumber(),
2951 fBoard->GetCMCSerialNumber(), chipIndex, static_cast<int>(fBoard->GetFrequency() * 1000));
2952 fCalibFile = fopen(str, "wb");
2953 if (fCalibFile == NULL) {
2954 printf("Error: Cannot write to file \"%s\"\n", str);
2955 return false;
2956 }
2957
2958 // Write File
2959 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
2960 chn = data->fChannel[ii];
2961 for (j = 0; j < kNumberOfBins; j++) {
2962 fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
2963 fwrite(&chn->fGain[j], 2, 1, fCalibFile);
2964 }
2965 }
2966 fclose(fCalibFile);
2967
2968 printf("Calibration successfully written to\n\"%s\"\n", str);
2969 return true;
2970}
2971
2972/*------------------------------------------------------------------*/
2973
2974void ResponseCalibration::CalibrationTrigger(int mode, double voltage)
2975{
2976 fBoard->Reinit();
2977 fBoard->EnableAcal(mode, voltage);
2978 fBoard->StartDomino();
2979 fBoard->SoftTrigger();
2980 while (fBoard->IsBusy()) {
2981 }
2982}
2983
2984/*------------------------------------------------------------------*/
2985
2986void ResponseCalibration::CalibrationStart(double voltage)
2987{
2988 fBoard->SetDominoMode(1);
2989 fBoard->EnableAcal(0, voltage);
2990 fBoard->StartDomino();
2991 fBoard->IsBusy();
2992 fBoard->IsBusy();
2993 fBoard->IsBusy();
2994}
2995
2996/*------------------------------------------------------------------*/
2997
2998bool ResponseCalibration::RecordCalibrationPoints(int chipNumber)
2999{
3000 if (!fInitialized)
3001 return true;
3002 if (fBoard->GetChipVersion() == 3)
3003 return RecordCalibrationPointsV4(chipNumber);
3004 else
3005 return RecordCalibrationPointsV3(chipNumber);
3006}
3007
3008/*------------------------------------------------------------------*/
3009
3010bool ResponseCalibration::RecordCalibrationPointsV3(int chipNumber)
3011{
3012
3013 int j, k, ii;
3014 int notdone, nsample;
3015 double voltage;
3016 float mean;
3017 const double minVolt = 0.006;
3018 const double xpos[50] =
3019 { 0.010, 0.027, 0.052, 0.074, 0.096, 0.117, 0.136, 0.155, 0.173, 0.191, 0.208, 0.226, 0.243, 0.260,
3020 0.277, 0.294, 0.310,
3021 0.325, 0.342, 0.358, 0.374, 0.390, 0.406, 0.422, 0.439, 0.457, 0.477, 0.497, 0.520, 0.546, 0.577, 0.611,
3022 0.656, 0.710,
3023 0.772, 0.842, 0.916,
3024 0.995, 1.075, 1.157, 1.240, 1.323, 1.407, 1.490, 1.575, 1.659, 1.744, 1.829, 1.914, 2.000
3025 };
3026
3027 // Initialisations
3028 if (fCurrentLowVoltPoint == 0) {
3029 fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0);
3030 // Record Temperature
3031 fCalibrationData[chipNumber]->fStartTemperature = static_cast<float>(fBoard->GetTemperature());
3032 }
3033 // Record current Voltage
3034 if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
3035 voltage = (xpos[0] - minVolt) * fCurrentLowVoltPoint / static_cast<double>(fNumberOfPointsLowVolt) + minVolt;
3036 else
3037 voltage = xpos[fCurrentPoint];
3038 fBoard->SetCalibVoltage(voltage);
3039 fResponseY[fCurrentPoint + fCurrentLowVoltPoint] = static_cast<float>(voltage) * 1000;
3040
3041 // Loop Over Number Of Samples For Statistics
3042 for (j = 0; j < fNumberOfSamples; j++) {
3043 // Read Out Second Part of the Waveform
3044 CalibrationTrigger(3, voltage);
3045 fBoard->TransferWaves();
3046 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3047 fBoard->GetADCWave(chipNumber, ii, fWaveFormMode3[ii][j]);
3048 }
3049 // Read Out First Part of the Waveform
3050 CalibrationStart(voltage);
3051 CalibrationTrigger(2, voltage);
3052 fBoard->TransferWaves();
3053 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3054 fBoard->GetADCWave(chipNumber, ii, fWaveFormMode2[ii][j]);
3055 }
3056 CalibrationStart(voltage);
3057 }
3058 // Average Sample Points
3059 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3060 for (k = 0; k < kNumberOfBins; k++) {
3061 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = 0;
3062 for (j = 0; j < fNumberOfSamples; j++) {
3063 fSampleUsed[j] = 1;
3064 if (k < fNumberOfMode2Bins)
3065 fSamples[j] = fWaveFormMode2[ii][j][k];
3066 else
3067 fSamples[j] = fWaveFormMode3[ii][j][k];
3068 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] += fSamples[j];
3069 }
3070 mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / fNumberOfSamples;
3071 notdone = 1;
3072 nsample = fNumberOfSamples;
3073 while (notdone) {
3074 notdone = 0;
3075 for (j = 0; j < fNumberOfSamples; j++) {
3076 if (fSampleUsed[j] && abs(static_cast<int>(fSamples[j] - mean)) > 3) {
3077 notdone = 1;
3078 fSampleUsed[j] = 0;
3079 nsample--;
3080 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] -= fSamples[j];
3081 mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / nsample;
3082 }
3083 }
3084 }
3085 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = mean;
3086 }
3087 }
3088 if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
3089 fCurrentLowVoltPoint++;
3090 else
3091 fCurrentPoint++;
3092
3093 if (fCurrentPoint == fNumberOfPoints) {
3094 fCalibrationData[chipNumber]->fEndTemperature = static_cast<float>(fBoard->GetTemperature());
3095 fRecorded = true;
3096 fFitted = false;
3097 fOffset = false;
3098 fCalibrationData[chipNumber]->fRead = false;
3099 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
3100 fBoard->SetCalibVoltage(0.0);
3101 fBoard->EnableAcal(1, 0.0);
3102 fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0.0);
3103 return true;
3104 }
3105
3106 return false;
3107}
3108
3109/*------------------------------------------------------------------*/
3110
3111bool ResponseCalibration::RecordCalibrationPointsV4(int chipNumber)
3112{
3113 int i, j, k, n;
3114 double voltage, s, s2, average, sigma;
3115
3116 if (fCurrentPoint == 0) {
3117 fBoard->SetDominoMode(1);
3118 fBoard->EnableAcal(1,0);
3119 fBoard->SoftTrigger();
3120 while (fBoard->IsBusy());
3121 fBoard->StartDomino();
3122 fCalibrationData[chipNumber]->fStartTemperature = static_cast<float>(fBoard->GetTemperature());
3123 }
3124 voltage = 1.0 * fCurrentPoint / (static_cast<double>(fNumberOfPoints) - 1) + 0.1;
3125 fBoard->SetCalibVoltage(voltage);
3126 Sleep(10);
3127 fBoard->SetCalibVoltage(voltage);
3128 Sleep(10);
3129
3130 // One dummy cycle for unknown reasons
3131 fBoard->SoftTrigger();
3132 while (fBoard->IsBusy());
3133 fBoard->StartDomino();
3134 //Sleep(50);
3135 fBoard->TransferWaves();
3136
3137 // Loop over number of samples for statistics
3138 for (i = 0; i < fNumberOfSamples; i++) {
3139#ifdef DEBUG_CALIB
3140 printf("%d \r", fNumberOfSamples-i);
3141#endif
3142 fBoard->SoftTrigger();
3143 while (fBoard->IsBusy());
3144 fBoard->StartDomino();
3145 //Sleep(50);
3146 fBoard->TransferWaves();
3147 for (j = 0; j < kNumberOfCalibChannels; j++) {
3148 fBoard->GetADCWave(chipNumber, j, fWaveFormMode3[j][i]);
3149 }
3150 }
3151
3152 for (i = 0; i < kNumberOfCalibChannels; i++) {
3153 for (k = 0; k < kNumberOfBins; k++) {
3154 s = s2 = 0;
3155
3156 for (j=0 ; j<fNumberOfSamples ; j++) {
3157 s += fWaveFormMode3[i][j][k];
3158 s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
3159 }
3160 n = fNumberOfSamples;
3161 average = s / n;
3162 sigma = sqrt( (n*s2 - s*s) / (n*(n - 1)) );
3163
3164 fResponseX[i][k][fCurrentPoint] = static_cast<float>(average);
3165 }
3166 }
3167
3168#ifdef DEBUG_CALIB
3169 for (j = 0; j < fNumberOfSamples; j++)
3170 printf("%d ", fWaveFormMode3[1][j][10]);
3171
3172 s = s2 = 0;
3173 for (j = 0; j < fNumberOfSamples; j++) {
3174 s += fWaveFormMode3[i][j][k];
3175 s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
3176 }
3177 n = fNumberOfSamples;
3178 average = s / n;
3179 sigma = sqrt( (n*s2 - s*s) / (n*(n - 1)) );
3180
3181 printf("\n");
3182 printf("%1.2lf V: %6.1lf (%1.4lf)\n", voltage,
3183 fResponseX[1][10][fCurrentPoint],
3184 fResponseX[1][10][fCurrentPoint]/4096.0);
3185#endif
3186
3187 fCurrentPoint++;
3188 if (fCurrentPoint == fNumberOfPoints) {
3189 fCalibrationData[chipNumber]->fEndTemperature = static_cast<float>(fBoard->GetTemperature());
3190 fRecorded = true;
3191 return true;
3192 }
3193
3194 return false;
3195}
3196
3197/*------------------------------------------------------------------*/
3198
3199bool ResponseCalibration::FitCalibrationPoints(int chipNumber)
3200{
3201 if (!fRecorded || fFitted)
3202 return true;
3203 if (fBoard->GetChipVersion() == 3)
3204 return FitCalibrationPointsV4(chipNumber);
3205 else
3206 return FitCalibrationPointsV3(chipNumber);
3207}
3208
3209/*------------------------------------------------------------------*/
3210
3211bool ResponseCalibration::FitCalibrationPointsV3(int chipNumber)
3212{
3213 int i, j, k;
3214 float x1, x2, y1, y2;
3215 float uu;
3216 float yc, yr;
3217 float xminExt, xrangeExt;
3218 float xmin, xrange;
3219 float average, averageError, averageExt, averageErrorExt;
3220 unsigned short i0, i1;
3221
3222 CalibrationData *data = fCalibrationData[chipNumber];
3223 CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
3224
3225 data->DeletePreCalculatedBSpline();
3226
3227 if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
3228 data->fNumberOfLimitGroups = 0;
3229 data->fMin = 100000;
3230 data->fMax = -100000;
3231 for (i = 0; i < kNumberOfCalibChannels; i++) {
3232 for (j = 0; j < kNumberOfBins; j++) {
3233 if (data->fMin > fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1])
3234 data->fMin = fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1];
3235 if (data->fMax < fResponseX[i][j][fNumberOfPointsLowVolt])
3236 data->fMax = fResponseX[i][j][fNumberOfPointsLowVolt];
3237 }
3238 }
3239 }
3240
3241 // Low Volt
3242 i0 = static_cast<unsigned short>(fResponseX[fCurrentFitChannel][fCurrentFitBin][0]);
3243 i1 = static_cast<unsigned short>(fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt]) + 1;
3244 chn->fLookUpOffset[fCurrentFitBin] = i0;
3245 delete chn->fLookUp[fCurrentFitBin];
3246 if (i0 - i1 + 1 < 2) {
3247 chn->fNumberOfLookUpPoints[fCurrentFitBin] = 2;
3248 chn->fLookUp[fCurrentFitBin] = new unsigned char[2];
3249 chn->fLookUp[fCurrentFitBin][0] = 0;
3250 chn->fLookUp[fCurrentFitBin][1] = 0;
3251 } else {
3252 chn->fNumberOfLookUpPoints[fCurrentFitBin] = i0 - i1 + 1;
3253 chn->fLookUp[fCurrentFitBin] = new unsigned char[i0 - i1 + 1];
3254 for (i = 0; i < i0 - i1 + 1; i++) {
3255 for (j = 0; j < fNumberOfPointsLowVolt; j++) {
3256 if (i0 - i >= fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1]) {
3257 x1 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j];
3258 x2 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1];
3259 y1 = fResponseY[j];
3260 y2 = fResponseY[j + 1];
3261 chn->fLookUp[fCurrentFitBin][i] = static_cast<unsigned char>(((y2 - y1) * (i0 - i - x1) / (x2 - x1) + y1)/fPrecision);
3262 break;
3263 }
3264 }
3265 }
3266 }
3267
3268
3269 // Copy Points
3270 for (i = 0; i < fNumberOfPoints; i++) {
3271 fPntX[0][i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt + i];
3272 fPntY[0][i] = fResponseY[fNumberOfPointsLowVolt + i];
3273 }
3274 // Fit BSpline
3275 for (i = 0; i < fNumberOfPoints; i++) {
3276 fUValues[0][i] = static_cast<float>(1 - i / (fNumberOfPoints - 1.));
3277 }
3278 if (!Approx(fPntX[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fResX[fCurrentFitBin]))
3279 return true;
3280 if (!Approx(fPntY[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fRes[fCurrentFitBin]))
3281 return true;
3282
3283
3284 // X constant fit
3285 for (k = 0; k < fNumberOfXConstPoints - 2; k++) {
3286 fPntX[1][k + 1] =
3287 GetValue(fResX[fCurrentFitBin], static_cast<float>(1 - k / static_cast<float>(fNumberOfXConstPoints - 3)),
3288 fNumberOfGridPoints);
3289 fPntY[1][k + 1] =
3290 GetValue(fRes[fCurrentFitBin], static_cast<float>(1 - k / static_cast<float>(fNumberOfXConstPoints - 3)),
3291 fNumberOfGridPoints);
3292 }
3293 xmin = fPntX[1][fNumberOfXConstPoints - 2];
3294 xrange = fPntX[1][1] - xmin;
3295
3296 for (i = 0; i < fNumberOfXConstPoints - 2; i++) {
3297 fUValues[1][i + 1] = (fPntX[1][i + 1] - xmin) / xrange;
3298 }
3299
3300 if (!Approx
3301 (&fPntY[1][1], &fUValues[1][1], fNumberOfXConstPoints - 2, fNumberOfXConstGridPoints,
3302 chn->fTempData))
3303 return true;
3304
3305
3306 // Error statistics
3307 if (fShowStatistics) {
3308 for (i = 0; i < fNumberOfPoints; i++) {
3309 uu = (fPntX[0][i] - xmin) / xrange;
3310 yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
3311 yr = fPntY[0][i];
3312 fStatisticsApprox[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
3313 }
3314 }
3315 // Add min and max point
3316 chn->fLimitGroup[fCurrentFitBin] = 0;
3317 while (xmin - kBSplineXMinOffset > data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin]) {
3318 chn->fLimitGroup[fCurrentFitBin]++;
3319 }
3320 if (data->fNumberOfLimitGroups <= chn->fLimitGroup[fCurrentFitBin])
3321 data->fNumberOfLimitGroups = chn->fLimitGroup[fCurrentFitBin] + 1;
3322 xminExt = data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin];
3323 xrangeExt = data->fMax - xminExt;
3324
3325 fPntX[1][0] = data->fMax;
3326 uu = (fPntX[1][0] - xmin) / xrange;
3327 fPntY[1][0] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
3328
3329 fPntX[1][fNumberOfXConstPoints - 1] = xminExt;
3330 uu = (fPntX[1][fNumberOfXConstPoints - 1] - xmin) / xrange;
3331 fPntY[1][fNumberOfXConstPoints - 1] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
3332
3333 for (i = 0; i < fNumberOfXConstPoints; i++) {
3334 fUValues[1][i] = (fPntX[1][i] - xminExt) / xrangeExt;
3335 }
3336
3337 if (!Approx
3338 (fPntY[1], fUValues[1], fNumberOfXConstPoints, fNumberOfXConstGridPoints, chn->fTempData))
3339 return true;
3340
3341 // Error statistics
3342 if (fShowStatistics) {
3343 for (i = 0; i < fNumberOfPoints; i++) {
3344 uu = (fPntX[0][i] - xminExt) / xrangeExt;
3345 yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
3346 yr = fPntY[0][i];
3347 fStatisticsApproxExt[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
3348 }
3349 }
3350 for (i = 0; i < fNumberOfXConstGridPoints; i++) {
3351 chn->fData[fCurrentFitBin][i] = static_cast<short>(chn->fTempData[i] / fPrecision);
3352 }
3353
3354
3355 // Write end of file
3356 fCurrentFitBin++;
3357 if (fCurrentFitBin == kNumberOfBins) {
3358 fCurrentFitChannel++;
3359 fCurrentFitBin = 0;
3360 }
3361 if (fCurrentFitChannel == kNumberOfCalibChannels) {
3362 if (fShowStatistics) {
3363 for (i = 0; i < fNumberOfPoints; i++) {
3364 average = 0;
3365 averageError = 0;
3366 averageExt = 0;
3367 averageErrorExt = 0;
3368 for (j = 0; j < kNumberOfCalibChannels * kNumberOfBins; j++) {
3369 average += fStatisticsApprox[i][j];
3370 averageError += fStatisticsApprox[i][j] * fStatisticsApprox[i][j];
3371 averageExt += fStatisticsApproxExt[i][j];
3372 averageErrorExt += fStatisticsApproxExt[i][j] * fStatisticsApproxExt[i][j];
3373 }
3374 average /= kNumberOfCalibChannels * kNumberOfBins;
3375 averageError =
3376 sqrt((averageError -
3377 average * average / kNumberOfCalibChannels * kNumberOfBins) / (kNumberOfCalibChannels *
3378 kNumberOfBins - 1));
3379 averageExt /= kNumberOfCalibChannels * kNumberOfBins;
3380 averageErrorExt =
3381 sqrt((averageErrorExt -
3382 averageExt * averageExt / kNumberOfCalibChannels * kNumberOfBins) /
3383 (kNumberOfCalibChannels * kNumberOfBins - 1));
3384 printf("Error at %3.1f V : % 2.3f +- % 2.3f ; % 2.3f +- % 2.3f\n", fPntY[0][i], average,
3385 averageError, averageExt, averageErrorExt);
3386 }
3387 }
3388 fFitted = true;
3389 fOffset = false;
3390 fCalibrationData[chipNumber]->fRead = true;
3391 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
3392 data->PreCalculateBSpline();
3393 return true;
3394 }
3395 return false;
3396}
3397
3398/*------------------------------------------------------------------*/
3399
3400bool ResponseCalibration::FitCalibrationPointsV4(int chipNumber)
3401{
3402 if (!fRecorded || fFitted)
3403 return true;
3404 int i;
3405 double par[2];
3406
3407 CalibrationData *data = fCalibrationData[chipNumber];
3408 CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
3409
3410 if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
3411 for (i = 0; i < fNumberOfPoints; i++)
3412 fWWFit[i] = 1;
3413 }
3414
3415 for (i = 0; i < fNumberOfPoints; i++) {
3416 fXXFit[i] = 1.0 * i / (static_cast<double>(fNumberOfPoints) - 1) + 0.1;
3417 fYYFit[i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][i];
3418 if (fCurrentFitBin == 10 && fCurrentFitChannel == 1) {
3419 fXXSave[i] = fXXFit[i];
3420 fYYSave[i] = fYYFit[i];
3421 }
3422 }
3423
3424 DRSBoard::LinearRegression(fXXFit, fYYFit, fNumberOfPoints, &par[1], &par[0]);
3425 chn->fOffset[fCurrentFitBin] = static_cast<short>(par[0] + 0.5);
3426 chn->fGain[fCurrentFitBin] = static_cast<short>(par[1] + 0.5);
3427
3428 if (fCurrentFitChannel == 1 && fCurrentFitBin == 10) {
3429#ifdef DEBUG_CALIB
3430 printf("gain:%d, offset:%d\n", chn->fGain[10], chn->fOffset[10]);
3431#endif
3432 for (i = 0; i < fNumberOfPoints; i++) {
3433 fXXSave[i] = fXXFit[i];
3434 fYYSave[i] = (fYYFit[i] - chn->fOffset[10]) / chn->fGain[10] - fXXFit[i];
3435 }
3436 }
3437
3438 fCurrentFitBin++;
3439 if (fCurrentFitBin == kNumberOfBins) {
3440 fCurrentFitChannel++;
3441 fCurrentFitBin = 0;
3442 }
3443 if (fCurrentFitChannel == kNumberOfCalibChannels) {
3444 fFitted = true;
3445 fOffset = true;
3446 fCalibrationData[chipNumber]->fRead = true;
3447 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
3448 return true;
3449 }
3450
3451 return false;
3452}
3453
3454unsigned int millitime()
3455{
3456 struct timeval tv;
3457
3458 gettimeofday(&tv, NULL);
3459
3460 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3461}
3462
3463/*------------------------------------------------------------------*/
3464
3465bool ResponseCalibration::OffsetCalibration(int chipNumber)
3466{
3467 if (!fFitted || fOffset)
3468 return true;
3469 int k, ii, j;
3470 int t1, t2;
3471 float mean,error;
3472 CalibrationData *data = fCalibrationData[chipNumber];
3473 CalibrationData::CalibrationDataChannel * chn;
3474
3475 if (fCurrentSample == 0) {
3476 data->fHasOffsetCalibration = false;
3477 fBoard->SetCalibVoltage(0.0);
3478 fBoard->EnableAcal(1, 0.0);
3479 }
3480 // Loop Over Number Of Samples For Statistics
3481 t1 = millitime();
3482 fBoard->SoftTrigger();
3483 while (fBoard->IsBusy()) {
3484 }
3485 fBoard->TransferWaves();
3486 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3487 fBoard->GetADCWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
3488 fBoard->CalibrateWaveform(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample], fWaveFormOffset[ii][fCurrentSample],
3489 true, false, false, 0);
3490 }
3491 fBoard->StartDomino();
3492 fBoard->IsBusy();
3493 fBoard->IsBusy();
3494 fBoard->IsBusy();
3495 t2 = millitime();
3496 while (t2 - t1 < (1000 / fTriggerFrequency)) {
3497 t2 = millitime();
3498 }
3499 fCurrentSample++;
3500
3501 if (fCurrentSample == fNumberOfSamples) {
3502 // Average Sample Points
3503 float *sample = new float[fNumberOfSamples];
3504 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3505 chn = data->fChannel[ii];
3506 for (k = 0; k < kNumberOfBins; k++) {
3507 for (j = 0; j < fNumberOfSamples; j++)
3508 sample[j] = static_cast<float>(fWaveFormOffset[ii][j][k]);
3509 Average(1, sample, fNumberOfSamples, mean, error, 2);
3510 chn->fOffset[k] = static_cast<short>(mean);
3511 for (j = 0; j < fNumberOfSamples; j++)
3512 sample[j] = fWaveFormOffsetADC[ii][j][k];
3513 Average(1, sample, fNumberOfSamples, mean, error, 2);
3514 chn->fOffsetADC[k] = static_cast<unsigned short>(mean);
3515 }
3516 }
3517 fOffset = true;
3518 fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
3519 delete sample;
3520 return true;
3521 }
3522
3523 return false;
3524}
3525
3526/*------------------------------------------------------------------*/
3527
3528void ResponseCalibration::InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
3529 int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
3530 int numberOfXConstGridPoints, double triggerFrequency,
3531 int showStatistics)
3532{
3533 int ii, j, i;
3534 fInitialized = true;
3535 fNumberOfPointsLowVolt = numberOfPointsLowVolt;
3536 fNumberOfPoints = numberOfPoints;
3537 fNumberOfMode2Bins = numberOfMode2Bins;
3538 fNumberOfSamples = numberOfSamples;
3539 fNumberOfGridPoints = numberOfGridPoints;
3540 fNumberOfXConstPoints = numberOfXConstPoints;
3541 fNumberOfXConstGridPoints = numberOfXConstGridPoints;
3542 fTriggerFrequency = triggerFrequency;
3543 fShowStatistics = showStatistics;
3544 fCurrentPoint = 0;
3545 fCurrentSample = 0;
3546 fCurrentFitChannel = 0;
3547 fCurrentFitBin = 0;
3548 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3549 for (j = 0; j < kNumberOfBins; j++) {
3550 fResponseX[ii][j] = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
3551 }
3552 }
3553 fResponseY = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
3554 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3555 fWaveFormMode3[ii] = new unsigned short *[fNumberOfSamples];
3556 fWaveFormMode2[ii] = new unsigned short *[fNumberOfSamples];
3557 fWaveFormOffset[ii] = new short *[fNumberOfSamples];
3558 fWaveFormOffsetADC[ii] = new unsigned short *[fNumberOfSamples];
3559 for (i = 0; i < fNumberOfSamples; i++) {
3560 fWaveFormMode3[ii][i] = new unsigned short[kNumberOfBins];
3561 fWaveFormMode2[ii][i] = new unsigned short[kNumberOfBins];
3562 fWaveFormOffset[ii][i] = new short[kNumberOfBins];
3563 fWaveFormOffsetADC[ii][i] = new unsigned short[kNumberOfBins];
3564 }
3565 }
3566 fSamples = new unsigned short[fNumberOfSamples];
3567 fSampleUsed = new int[fNumberOfSamples];
3568
3569 for (j = 0; j < kNumberOfBins; j++) {
3570 fRes[j] = new float[fNumberOfGridPoints];
3571 fResX[j] = new float[fNumberOfGridPoints];
3572 }
3573 for (i = 0; i < 2; i++) {
3574 fPntX[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
3575 fPntY[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
3576 fUValues[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
3577 }
3578 fXXFit = new double[fNumberOfPoints];
3579 fYYFit = new double[fNumberOfPoints];
3580 fWWFit = new double[fNumberOfPoints];
3581 fYYFitRes = new double[fNumberOfPoints];
3582 fYYSave = new double[fNumberOfPoints];
3583 fXXSave = new double[fNumberOfPoints];
3584
3585 fStatisticsApprox = new float *[fNumberOfPoints];
3586 fStatisticsApproxExt = new float *[fNumberOfPoints];
3587 for (i = 0; i < fNumberOfPoints; i++) {
3588 fStatisticsApprox[i] = new float[kNumberOfCalibChannels * kNumberOfBins];
3589 fStatisticsApproxExt[i] = new float[kNumberOfCalibChannels * kNumberOfBins];
3590 }
3591 for (i = 0; i < kNumberOfChips; i++) {
3592 fCalibrationData[i] = new CalibrationData(numberOfXConstGridPoints);
3593 }
3594}
3595
3596/*------------------------------------------------------------------*/
3597
3598void ResponseCalibration::DeleteFields()
3599{
3600 if (!fInitialized)
3601 return;
3602 fInitialized = false;
3603 int ii, j, i;
3604 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3605 for (j = 0; j < kNumberOfBins; j++) {
3606 delete fResponseX[ii][j];
3607 }
3608 }
3609 delete fResponseY;
3610 for (ii = 0; ii < kNumberOfCalibChannels; ii++) {
3611 for (i = 0; i < fNumberOfSamples; i++) {
3612 if (fWaveFormMode3[ii] != NULL)
3613 delete fWaveFormMode3[ii][i];
3614 if (fWaveFormMode2[ii] != NULL)
3615 delete fWaveFormMode2[ii][i];
3616 if (fWaveFormOffset[ii] != NULL)
3617 delete fWaveFormOffset[ii][i];
3618 if (fWaveFormOffsetADC[ii] != NULL)
3619 delete fWaveFormOffsetADC[ii][i];
3620 }
3621 delete fWaveFormMode3[ii];
3622 delete fWaveFormMode2[ii];
3623 delete fWaveFormOffset[ii];
3624 delete fWaveFormOffsetADC[ii];
3625 }
3626 delete fSamples;
3627 delete fSampleUsed;
3628
3629 for (j = 0; j < kNumberOfBins; j++) {
3630 delete fRes[j];
3631 delete fResX[j];
3632 }
3633 for (i = 0; i < 2; i++) {
3634 delete fPntX[i];
3635 delete fPntY[i];
3636 delete fUValues[i];
3637 }
3638 delete fXXFit;
3639 delete fYYFit;
3640 delete fWWFit;
3641 delete fYYFitRes;
3642 delete fYYSave;
3643 delete fXXSave;
3644
3645 for (i = 0; i < fNumberOfPoints; i++) {
3646 delete fStatisticsApprox[i];
3647 delete fStatisticsApproxExt[i];
3648 }
3649 delete fStatisticsApprox;
3650 delete fStatisticsApproxExt;
3651 for (i = 0; i < kNumberOfChips; i++)
3652 delete fCalibrationData[i];
3653}
3654
3655/*------------------------------------------------------------------*/
3656
3657double ResponseCalibration::GetTemperature(unsigned int chipIndex)
3658{
3659 if (fCalibrationData[chipIndex]==NULL)
3660 return 0;
3661 if (!fCalibrationData[chipIndex]->fRead)
3662 return 0;
3663 return (fCalibrationData[chipIndex]->fStartTemperature + fCalibrationData[chipIndex]->fEndTemperature) / 2;
3664}
3665
3666/*------------------------------------------------------------------*/
3667
3668bool ResponseCalibration::Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
3669 short *uWaveform, int triggerCell, float threshold)
3670{
3671 int i;
3672 int hasOffset;
3673 bool aboveThreshold;
3674 float wave, v;
3675 int j,irot;
3676
3677 CalibrationData *data = fCalibrationData[chipIndex];
3678 CalibrationData::CalibrationDataChannel * chn;
3679
3680 if (channel > kNumberOfCalibChannels || data == NULL) {
3681 for (i = 0; i < kNumberOfBins; i++) {
3682 uWaveform[i] = adcWaveform[i];
3683 }
3684 return true;
3685 }
3686 if (!data->fRead) {
3687 for (i = 0; i < kNumberOfBins; i++) {
3688 uWaveform[i] = adcWaveform[i];
3689 }
3690 return true;
3691 }
3692
3693 chn = data->fChannel[channel];
3694
3695 hasOffset = data->fHasOffsetCalibration;
3696 aboveThreshold = (threshold == 0); // If threshold equal zero, always return true
3697
3698 // Calibrate
3699 for (i = 0; i < kNumberOfBins; i++) {
3700 if (fBoard->GetChipVersion() != 3) {
3701 irot = i;
3702 if (triggerCell > -1)
3703 irot = (triggerCell + i) % kNumberOfBins;
3704 if (adcWaveform[irot] > chn->fLookUpOffset[irot]) {
3705 uWaveform[i] =
3706 ((chn->fLookUp[irot][0] - chn->fLookUp[irot][1]) * (adcWaveform[irot] - chn->fLookUpOffset[irot]) +
3707 chn->fLookUp[irot][0]);
3708 } else if (adcWaveform[irot] <= chn->fLookUpOffset[irot]
3709 && adcWaveform[irot] > chn->fLookUpOffset[irot] - chn->fNumberOfLookUpPoints[irot]) {
3710 uWaveform[i] = chn->fLookUp[irot][chn->fLookUpOffset[irot] - adcWaveform[irot]];
3711 } else {
3712 wave = 0;
3713 for (j = 0; j < kBSplineOrder; j++) {
3714 wave += chn->fData[irot][data->fBSplineOffsetLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]] + j]
3715 * data->fBSplineLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]][j];
3716 }
3717 uWaveform[i] = static_cast<short>(wave);
3718 }
3719 // Offset Calibration
3720 if (hasOffset)
3721 uWaveform[i] -= chn->fOffset[irot];
3722 } else {
3723 if (chn->fGain[i] > 3800) {
3724 //if (channel == 1 && i == 10)
3725 // printf("gain:%d offset:%d value:%d\n", chn->fGain[i], chn->fOffset[i], adcWaveform[i]);
3726 v = static_cast<float>(adcWaveform[i] - chn->fOffset[i]) / chn->fGain[i];
3727 uWaveform[i] = static_cast<short>(v * 1000 / GetPrecision() + 0.5);
3728 } else
3729 uWaveform[i] = 0;
3730 }
3731
3732 // Check for Threshold
3733 if (!aboveThreshold) {
3734 if (uWaveform[i] >= threshold)
3735 aboveThreshold = true;
3736 }
3737 }
3738 return aboveThreshold;
3739}
3740
3741/*------------------------------------------------------------------*/
3742
3743bool ResponseCalibration::SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
3744 unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel)
3745{
3746 int i;
3747 CalibrationData *data = fCalibrationData[chipIndex];
3748 CalibrationData::CalibrationDataChannel * chn;
3749
3750 if (channel >= kNumberOfCalibChannels || data == NULL)
3751 return false;
3752 if (!data->fRead || !data->fHasOffsetCalibration)
3753 return false;
3754
3755 chn = data->fChannel[channel];
3756 for (i = 0; i < kNumberOfBins; i++)
3757 adcCalibratedWaveform[i] = adcWaveform[i]-chn->fOffsetADC[i]+newBaseLevel;
3758 return true;
3759}
3760
3761
3762/*------------------------------------------------------------------*/
3763
3764bool ResponseCalibration::ReadCalibration(unsigned int chipIndex)
3765{
3766 if (fBoard->GetChipVersion() == 3)
3767 return ReadCalibrationV4(chipIndex);
3768 else
3769 return ReadCalibrationV3(chipIndex);
3770}
3771
3772/*------------------------------------------------------------------*/
3773
3774bool ResponseCalibration::ReadCalibrationV3(unsigned int chipIndex)
3775{
3776 int k, l, m, num;
3777 unsigned char ng;
3778 short tempShort;
3779 char fileName[2000];
3780 FILE *fileHandle;
3781 char calibDir[1000];
3782
3783 // Read Response Calibration
3784 delete fCalibrationData[chipIndex];
3785 fCalibrationData[chipIndex] = NULL;
3786
3787 fBoard->GetCalibrationDirectory(calibDir);
3788 sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
3789 fBoard->GetCMCSerialNumber(), fBoard->GetCMCSerialNumber(), chipIndex,
3790 static_cast<int>(fBoard->GetFrequency() * 1000));
3791
3792 fileHandle = fopen(fileName, "rb");
3793 if (fileHandle == NULL) {
3794 printf("Board %d --> Could not find response calibration file:\n", fBoard->GetCMCSerialNumber());
3795 printf("%s\n", fileName);
3796 return false;
3797 }
3798 // Number Of Grid Points
3799 num = fread(&ng, 1, 1, fileHandle);
3800 if (num != 1) {
3801 printf("Error while reading response calibration file '%s'\n", fileName);
3802 printf(" at 'NumberOfGridPoints'.\n");
3803 return false;
3804 }
3805
3806 fCalibrationData[chipIndex] = new CalibrationData(ng);
3807 CalibrationData *data = fCalibrationData[chipIndex];
3808 CalibrationData::CalibrationDataChannel * chn;
3809 data->fRead = true;
3810 data->fHasOffsetCalibration = 1;
3811 data->DeletePreCalculatedBSpline();
3812 fCalibrationValid[chipIndex] = true;
3813
3814 // Start Temperature
3815 num = fread(&tempShort, 2, 1, fileHandle);
3816 if (num != 1) {
3817 printf("Error while reading response calibration file '%s'\n", fileName);
3818 printf(" at 'StartTemperature'.\n");
3819 return false;
3820 }
3821 data->fStartTemperature = static_cast<float>(tempShort) / 10;
3822 // End Temperature
3823 num = fread(&tempShort, 2, 1, fileHandle);
3824 if (num != 1) {
3825 printf("Error while reading response calibration file '%s'\n", fileName);
3826 printf(" at 'EndTemperature'.\n");
3827 return false;
3828 }
3829 data->fEndTemperature = static_cast<float>(tempShort) / 10;
3830 if (fBoard->GetChipVersion() != 3) {
3831 // Min
3832 num = fread(&data->fMin, 4, 1, fileHandle);
3833 if (num != 1) {
3834 printf("Error while reading response calibration file '%s'\n", fileName);
3835 printf(" at 'Min'.\n");
3836 return false;
3837 }
3838 // Max
3839 num = fread(&data->fMax, 4, 1, fileHandle);
3840 if (num != 1) {
3841 printf("Error while reading response calibration file '%s'\n", fileName);
3842 printf(" at 'Max'.\n");
3843 return false;
3844 }
3845 // Number Of Limit Groups
3846 num = fread(&data->fNumberOfLimitGroups, 1, 1, fileHandle);
3847 if (num != 1) {
3848 printf("Error while reading response calibration file '%s'\n", fileName);
3849 printf(" at 'NumberOfLimitGroups'.\n");
3850 return false;
3851 }
3852 }
3853 // Read channel
3854 for (k = 0; k < kNumberOfCalibChannels; k++) {
3855 chn = data->fChannel[k];
3856 for (l = 0; l < kNumberOfBins; l++) {
3857 if (fBoard->GetChipVersion() != 3) {
3858 // Range Group
3859 num = fread(&chn->fLimitGroup[l], 1, 1, fileHandle);
3860 if (num != 1) {
3861 printf("Error while reading response calibration file '%s'\n", fileName);
3862 printf(" at 'RangeGroup' of channel %d bin %d.\n", k, l);
3863 return false;
3864 }
3865 // Look Up Offset
3866 num = fread(&chn->fLookUpOffset[l], 2, 1, fileHandle);
3867 if (num != 1) {
3868 printf("Error while reading response calibration file '%s'\n", fileName);
3869 printf(" at 'LookUpOffset' of channel %d bin %d.\n", k, l);
3870 return false;
3871 }
3872 // Number Of Look Up Points
3873 num = fread(&chn->fNumberOfLookUpPoints[l], 1, 1, fileHandle);
3874 if (num != 1) {
3875 printf("Error while reading response calibration file '%s'\n", fileName);
3876 printf(" at 'NumberOfLookUpPoints' of channel %d bin %d.\n", k, l);
3877 return false;
3878 }
3879 // Look Up Points
3880 delete chn->fLookUp[l];
3881 chn->fLookUp[l] = new unsigned char[chn->fNumberOfLookUpPoints[l]];
3882 for (m = 0; m < chn->fNumberOfLookUpPoints[l]; m++) {
3883 num = fread(&chn->fLookUp[l][m], 1, 1, fileHandle);
3884 if (num != 1) {
3885 printf("Error while reading response calibration file '%s'\n", fileName);
3886 printf(" at 'LookUp %d' of channel %d bin %d.\n", m, k, l);
3887 return false;
3888 }
3889 }
3890 // Points
3891 for (m = 0; m < data->fNumberOfGridPoints; m++) {
3892 num = fread(&chn->fData[l][m], 2, 1, fileHandle);
3893 if (num != 1) {
3894 printf("Error while reading response calibration file '%s'\n", fileName);
3895 printf(" at 'Point %d' of channel %d bin %d.\n", m, k, l);
3896 return false;
3897 }
3898 }
3899 // ADC Offset
3900 num = fread(&chn->fOffsetADC[l], 2, 1, fileHandle);
3901 if (num != 1) {
3902 printf("Error while reading response calibration file '%s'\n", fileName);
3903 printf(" at 'ADC Offset' of channel %d bin %d.\n", k, l);
3904 return false;
3905 }
3906 }
3907 // Offset
3908 num = fread(&chn->fOffset[l], 2, 1, fileHandle);
3909 if (num != 1) {
3910 printf("Error while reading response calibration file '%s'\n", fileName);
3911 printf(" at 'Offset' of channel %d bin %d.\n", k, l);
3912 return false;
3913 }
3914 if (fBoard->GetChipVersion() == 3) {
3915 // Gain
3916 num = fread(&chn->fGain[l], 2, 1, fileHandle);
3917 if (num != 1) {
3918 printf("Error while reading response calibration file '%s'\n", fileName);
3919 printf(" at 'Gain' of channel %d bin %d.\n", k, l);
3920 return false;
3921 }
3922 }
3923 }
3924 }
3925 fclose(fileHandle);
3926
3927 if (fBoard->GetChipVersion() != 3) {
3928 data->PreCalculateBSpline();
3929 }
3930
3931 return true;
3932}
3933
3934/*------------------------------------------------------------------*/
3935
3936bool ResponseCalibration::ReadCalibrationV4(unsigned int chipIndex)
3937{
3938 int k, l, num;
3939 char fileName[2000];
3940 FILE *fileHandle;
3941 char calibDir[1000];
3942
3943 // Read Response Calibration
3944
3945 fBoard->GetCalibrationDirectory(calibDir);
3946 sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
3947 fBoard->GetCMCSerialNumber(), fBoard->GetCMCSerialNumber(), chipIndex,
3948 static_cast<int>(fBoard->GetFrequency() * 1000));
3949
3950 fileHandle = fopen(fileName, "rb");
3951 if (fileHandle == NULL) {
3952 printf("Board %d --> Could not find response calibration file:\n", fBoard->GetCMCSerialNumber());
3953 printf("%s\n", fileName);
3954 return false;
3955 }
3956
3957 if (fInitialized)
3958 delete fCalibrationData[chipIndex];
3959 fCalibrationData[chipIndex] = new CalibrationData(1);
3960 CalibrationData *data = fCalibrationData[chipIndex];
3961 CalibrationData::CalibrationDataChannel * chn;
3962 data->fRead = true;
3963 data->fHasOffsetCalibration = 1;
3964 fCalibrationValid[chipIndex] = true;
3965 data->fStartTemperature = 0;
3966 data->fEndTemperature = 0;
3967
3968 // read channel
3969 for (k = 0; k < kNumberOfCalibChannels; k++) {
3970 chn = data->fChannel[k];
3971 for (l = 0; l < kNumberOfBins; l++) {
3972 // Offset
3973 num = fread(&chn->fOffset[l], 2, 1, fileHandle);
3974 if (num != 1) {
3975 printf("Error while reading response calibration file '%s'\n", fileName);
3976 printf(" at 'Offset' of channel %d bin %d.\n", k, l);
3977 return false;
3978 }
3979 if (fBoard->GetChipVersion() == 3) {
3980 // Gain
3981 num = fread(&chn->fGain[l], 2, 1, fileHandle);
3982 if (num != 1) {
3983 printf("Error while reading response calibration file '%s'\n", fileName);
3984 printf(" at 'Gain' of channel %d bin %d.\n", k, l);
3985 return false;
3986 }
3987 }
3988 }
3989 }
3990
3991 fclose(fileHandle);
3992 return true;
3993}
3994
3995/*------------------------------------------------------------------*/
3996
3997float ResponseCalibration::GetValue(float *coefficients, float u, int n)
3998{
3999 int j, ii;
4000 float bsplines[4];
4001 ii = CalibrationData::CalculateBSpline(n, u, bsplines);
4002
4003 float s = 0;
4004 for (j = 0; j < kBSplineOrder; j++) {
4005 s += coefficients[ii + j] * bsplines[j];
4006 }
4007 return s;
4008}
4009
4010/*------------------------------------------------------------------*/
4011
4012int ResponseCalibration::Approx(float *p, float *uu, int np, int nu, float *coef)
4013{
4014 int i, iu, j;
4015
4016 const int mbloc = 50;
4017 int ip = 0;
4018 int ir = 0;
4019 int mt = 0;
4020 int ileft, irow;
4021 float bu[kBSplineOrder];
4022 float *matrix[kBSplineOrder + 2];
4023 for (i = 0; i < kBSplineOrder + 2; i++)
4024 matrix[i] = new float[mbloc + nu + 1];
4025 for (iu = kBSplineOrder - 1; iu < nu; iu++) {
4026 for (i = 0; i < np; i++) {
4027 if (1 <= uu[i])
4028 ileft = nu - 1;
4029 else if (uu[i] < 0)
4030 ileft = kBSplineOrder - 2;
4031 else
4032 ileft = kBSplineOrder - 1 + static_cast<int>(uu[i] * (nu - kBSplineOrder + 1));
4033 if (ileft != iu)
4034 continue;
4035 irow = ir + mt;
4036 mt++;
4037 CalibrationData::CalculateBSpline(nu, uu[i], bu);
4038 for (j = 0; j < kBSplineOrder; j++) {
4039 matrix[j][irow] = bu[j];
4040 }
4041 matrix[kBSplineOrder][irow] = p[i];
4042 if (mt < mbloc)
4043 continue;
4044 LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
4045 mt = 0;
4046 }
4047 if (mt == 0)
4048 continue;
4049 LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
4050 mt = 0;
4051 }
4052 if (!LeastSquaresSolving(matrix, kBSplineOrder, ip, ir, coef, nu)) {
4053 for (i = 0; i < kBSplineOrder + 2; i++)
4054 delete matrix[i];
4055 return 0;
4056 }
4057
4058 for (i = 0; i < kBSplineOrder + 2; i++)
4059 delete matrix[i];
4060 return 1;
4061}
4062
4063/*------------------------------------------------------------------*/
4064
4065void ResponseCalibration::LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt)
4066{
4067 int i, j, l, mu, k, kh;
4068 float rho;
4069
4070 if (mt <= 0)
4071 return;
4072 if (jt != *ip) {
4073 if (jt > (*ir)) {
4074 for (i = 0; i < mt; i++) {
4075 for (j = 0; j < nb + 1; j++) {
4076 matrix[j][jt + mt - i] = matrix[j][(*ir) + mt - i];
4077 }
4078 }
4079 for (i = 0; i < jt - (*ir); i++) {
4080 for (j = 0; j < nb + 1; j++) {
4081 matrix[j][(*ir) + i] = 0;
4082 }
4083 }
4084 *ir = jt;
4085 }
4086 mu = min(nb - 1, (*ir) - (*ip) - 1);
4087 if (mu != 0) {
4088 for (l = 0; l < mu; l++) {
4089 k = min(l + 1, jt - (*ip));
4090 for (i = l + 1; i < nb; i++) {
4091 matrix[i - k][(*ip) + l + 1] = matrix[i][(*ip) + l + 1];
4092 }
4093 for (i = 0; i < k; i++) {
4094 matrix[nb - i - 1][(*ip) + l + 1] = 0;
4095 }
4096 }
4097 }
4098 *ip = jt;
4099 }
4100 kh = min(nb + 1, (*ir) + mt - (*ip));
4101
4102 for (i = 0; i < kh; i++) {
4103 Housholder(i, max(i + 1, (*ir) - (*ip)), (*ir) + mt - (*ip), matrix, i, (*ip), &rho, matrix, i + 1,
4104 (*ip), 1, nb - i);
4105 }
4106
4107 *ir = (*ip) + kh;
4108 if (kh < nb + 1)
4109 return;
4110 for (i = 0; i < nb; i++) {
4111 matrix[i][(*ir) - 1] = 0;
4112 }
4113}
4114
4115/*------------------------------------------------------------------*/
4116
4117int ResponseCalibration::LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n)
4118{
4119 int i, j, l, ii;
4120 float s, rsq;
4121 for (j = 0; j < n; j++) {
4122 x[j] = matrix[nb][j];
4123 }
4124 rsq = 0;
4125 if (n <= ir - 1) {
4126 for (j = n; j < ir; j++) {
4127 rsq += pow(matrix[nb][j], 2);
4128 }
4129 }
4130
4131 for (ii = 0; ii < n; ii++) {
4132 i = n - ii - 1;
4133 s = 0;
4134 l = max(0, i - ip);
4135 if (i != n - 1) {
4136 for (j = 1; j < min(n - i, nb); j++) {
4137 s += matrix[j + l][i] * x[i + j];
4138 }
4139 }
4140 if (matrix[l][i] == 0) {
4141 printf("Error in LeastSquaresSolving.\n");
4142 return 0;
4143 }
4144 x[i] = (x[i] - s) / matrix[l][i];
4145 }
4146 return 1;
4147}
4148
4149/*------------------------------------------------------------------*/
4150
4151void ResponseCalibration::Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up,
4152 float **c, int iC1, int iC2, int ice, int ncv)
4153{
4154 int i, j, incr;
4155 float tol = static_cast<float>(1e-20);
4156 float tolb = static_cast<float>(1e-24);
4157 float cl, clinv, sm, b;
4158
4159 if (lpivot < 0 || lpivot >= l1 || l1 > m - 1)
4160 return;
4161 cl = fabs(u[iU1][iU2 + lpivot]);
4162
4163 // Construct the transformation
4164 for (j = l1 - 1; j < m; j++)
4165 cl = max(fabsf(u[iU1][iU2 + j]), cl);
4166 if (cl < tol)
4167 return;
4168 clinv = 1 / cl;
4169 sm = pow(u[iU1][iU2 + lpivot] * clinv, 2);
4170 for (j = l1; j < m; j++) {
4171 sm = sm + pow(u[iU1][iU2 + j] * clinv, 2);
4172 }
4173 cl *= sqrt(sm);
4174 if (u[iU1][iU2 + lpivot] > 0)
4175 cl = -cl;
4176 *up = u[iU1][iU2 + lpivot] - cl;
4177 u[iU1][iU2 + lpivot] = cl;
4178
4179 if (ncv <= 0)
4180 return;
4181 b = (*up) * u[iU1][iU2 + lpivot];
4182 if (fabs(b) < tolb)
4183 return;
4184 if (b >= 0)
4185 return;
4186 b = 1 / b;
4187 incr = ice * (l1 - lpivot);
4188 for (j = 0; j < ncv; j++) {
4189 sm = c[iC1 + j][iC2 + lpivot] * (*up);
4190 for (i = l1; i < m; i++) {
4191 sm = sm + c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] * u[iU1][iU2 + i];
4192 }
4193 if (sm == 0)
4194 continue;
4195 sm *= b;
4196 c[iC1 + j][iC2 + lpivot] = c[iC1 + j][iC2 + lpivot] + sm * (*up);
4197 for (i = l1; i < m; i++) {
4198 c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] =
4199 c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] + sm * u[iU1][iU2 + i];
4200 }
4201 }
4202}
4203
4204/*------------------------------------------------------------------*/
4205
4206int ResponseCalibration::MakeDir(const char *path)
4207{
4208 struct stat buf;
4209 if (stat(path, &buf))
4210 return mkdir(path, 0711);
4211 return 0;
4212}
4213
4214/*------------------------------------------------------------------*/
4215
4216ResponseCalibration::ResponseCalibration(DRSBoard *board)
4217 :fBoard(board)
4218 ,fPrecision(0.1) // mV
4219 ,fInitialized(false)
4220 ,fRecorded(false)
4221 ,fFitted(false)
4222 ,fOffset(false)
4223 ,fNumberOfPointsLowVolt(0)
4224 ,fNumberOfPoints(0)
4225 ,fNumberOfMode2Bins(0)
4226 ,fNumberOfSamples(0)
4227 ,fNumberOfGridPoints(0)
4228 ,fNumberOfXConstPoints(0)
4229 ,fNumberOfXConstGridPoints(0)
4230 ,fTriggerFrequency(0)
4231 ,fShowStatistics(0)
4232 ,fCalibFile(0)
4233 ,fCurrentLowVoltPoint(0)
4234 ,fCurrentPoint(0)
4235 ,fCurrentSample(0)
4236 ,fCurrentFitChannel(0)
4237 ,fCurrentFitBin(0)
4238 ,fResponseY(0)
4239 ,fSamples(0)
4240 ,fSampleUsed(0)
4241 ,fXXFit(0)
4242 ,fYYFit(0)
4243 ,fWWFit(0)
4244 ,fYYFitRes(0)
4245 ,fYYSave(0)
4246 ,fXXSave(0)
4247 ,fStatisticsApprox(0)
4248 ,fStatisticsApproxExt(0)
4249{
4250 int i;
4251 // Initializing the Calibration Class
4252 CalibrationData::fIntRevers[0] = 0;
4253 for (i = 1; i < 2 * kBSplineOrder - 2; i++) {
4254 CalibrationData::fIntRevers[i] = static_cast<float>(1.) / i;
4255 }
4256 for (i = 0; i < kNumberOfChips; i++) {
4257 fCalibrationData[i] = NULL;
4258 }
4259 // Initializing the Calibration Creation
4260 fCalibrationValid[0] = false;
4261 fCalibrationValid[1] = false;
4262}
4263
4264/*------------------------------------------------------------------*/
4265
4266ResponseCalibration::~ResponseCalibration()
4267{
4268 // Deleting the Calibration Creation
4269 DeleteFields();
4270}
4271
4272/*------------------------------------------------------------------*/
4273
4274float ResponseCalibration::CalibrationData::fIntRevers[2 * kBSplineOrder - 2];
4275ResponseCalibration::CalibrationData::CalibrationData(int numberOfGridPoints)
4276 :fRead(false)
4277 ,fNumberOfGridPoints(numberOfGridPoints)
4278 ,fHasOffsetCalibration(0)
4279 ,fStartTemperature(0)
4280 ,fEndTemperature(0)
4281 ,fMin(0)
4282 ,fMax(0)
4283 ,fNumberOfLimitGroups(0)
4284{
4285 int i;
4286 for (i = 0; i < kNumberOfCalibChannels; i++) {
4287 fChannel[i] = new CalibrationDataChannel(numberOfGridPoints);
4288 }
4289 for (i = 0; i < kNumberOfADCBins; i++) {
4290 fBSplineOffsetLookUp[i] = NULL;
4291 fBSplineLookUp[i] = NULL;
4292 }
4293};
4294
4295/*------------------------------------------------------------------*/
4296
4297void ResponseCalibration::CalibrationData::PreCalculateBSpline()
4298{
4299 int i, j;
4300 float uu;
4301 float xmin, xrange;
4302 int nk = fNumberOfGridPoints - kBSplineOrder + 1;
4303 for (i = 0; i < kNumberOfADCBins; i++) {
4304 fBSplineLookUp[i] = new float *[fNumberOfLimitGroups];
4305 fBSplineOffsetLookUp[i] = new int[fNumberOfLimitGroups];
4306 for (j = 0; j < fNumberOfLimitGroups; j++) {
4307 fBSplineLookUp[i][j] = new float[kBSplineOrder];
4308 xmin = fMin + j * kBSplineXMinOffset;
4309 xrange = fMax - xmin;
4310 uu = (i - xmin) / xrange;
4311 if (i < xmin) {
4312 uu = 0;
4313 }
4314 if (i - xmin > xrange) {
4315 uu = 1;
4316 }
4317 fBSplineOffsetLookUp[i][j] = static_cast<int>(uu * nk);
4318 CalculateBSpline(fNumberOfGridPoints, uu, fBSplineLookUp[i][j]);
4319 }
4320 }
4321}
4322
4323/*------------------------------------------------------------------*/
4324
4325void ResponseCalibration::CalibrationData::DeletePreCalculatedBSpline()
4326{
4327 int i, j;
4328 for (i = 0; i < kNumberOfADCBins; i++) {
4329 if (fBSplineLookUp[i]!=NULL) {
4330 for (j = 0; j < fNumberOfLimitGroups; j++)
4331 delete fBSplineLookUp[i][j];
4332 }
4333 delete fBSplineLookUp[i];
4334 delete fBSplineOffsetLookUp[i];
4335 }
4336}
4337
4338/*------------------------------------------------------------------*/
4339
4340ResponseCalibration::CalibrationData::~CalibrationData()
4341{
4342 int i, j;
4343 for (i = 0; i < kNumberOfCalibChannels; i++) {
4344 delete fChannel[i];
4345 }
4346 for (i = 0; i < kNumberOfADCBins; i++) {
4347 if (fBSplineLookUp[i]!=NULL) {
4348 for (j = 0; j < fNumberOfLimitGroups; j++) {
4349 delete fBSplineLookUp[i][j];
4350 }
4351 }
4352 delete fBSplineLookUp[i];
4353 delete fBSplineOffsetLookUp[i];
4354 }
4355};
4356
4357/*------------------------------------------------------------------*/
4358
4359int ResponseCalibration::CalibrationData::CalculateBSpline(int nGrid, float value, float *bsplines)
4360{
4361 int minimum;
4362 int maximum;
4363 float xl;
4364
4365 int nk = nGrid - kBSplineOrder + 1;
4366 float vl = value * nk;
4367 int ivl = static_cast<int>(vl);
4368
4369 if (1 <= value) {
4370 xl = vl - nk + 1;
4371 minimum = 1 - nk;
4372 } else if (value < 0) {
4373 xl = vl;
4374 minimum = 0;
4375 } else {
4376 xl = vl - ivl;
4377 minimum = -ivl;
4378 }
4379 maximum = nk + minimum;
4380
4381 // printf("xl = %f\n",xl);
4382 float vm, vmprev;
4383 int jl, ju;
4384 int nb = 0;
4385
4386 bsplines[0] = 1;
4387 for (int i = 0; i < kBSplineOrder - 1; i++) {
4388 vmprev = 0;
4389 for (int j = 0; j < nb + 1; j++) {
4390 jl = max(minimum, j - nb);
4391 ju = min(maximum, j + 1);
4392 vm = bsplines[j] * fIntRevers[ju - jl];
4393 bsplines[j] = vm * (ju - xl) + vmprev;
4394 vmprev = vm * (xl - jl);
4395 }
4396 nb++;
4397 bsplines[nb] = vmprev;
4398 }
4399 return -minimum;
4400}
4401
4402/*------------------------------------------------------------------*/
4403
4404void ResponseCalibration::Average(int method,float *points,int numberOfPoints,float &mean,float &error,float sigmaBoundary)
4405{
4406 // Methods :
4407 // 0 : Average
4408 // 1 : Average inside sigmaBoundary*sigma
4409 int i;
4410 float sum = 0;
4411 float sumSquare = 0;
4412
4413 if (method == 0 || method == 1) {
4414 for (i = 0; i < numberOfPoints; i++) {
4415 sum += points[i];
4416 sumSquare += points[i]*points[i];
4417 }
4418
4419 mean = sum / numberOfPoints;
4420 error = sqrt((sumSquare - sum * sum / numberOfPoints) / (numberOfPoints - 1));
4421 }
4422 if (method == 1) {
4423 int numberOfGoodPoints = numberOfPoints;
4424 bool found = true;
4425 bool *goodSample = new bool[numberOfGoodPoints];
4426 for (i = 0; i < numberOfGoodPoints; i++)
4427 goodSample[i] = true;
4428
4429 while (found) {
4430 found = false;
4431 for (i = 0; i < numberOfPoints; i++) {
4432 if (goodSample[i] && fabs(points[i] - mean) > sigmaBoundary * error) {
4433 found = true;
4434 goodSample[i] = false;
4435 numberOfGoodPoints--;
4436 sum -= points[i];
4437 sumSquare -= points[i]*points[i];
4438 mean = sum/numberOfGoodPoints;
4439 error = sqrt((sumSquare - sum * sum / numberOfGoodPoints) / (numberOfGoodPoints - 1));
4440 }
4441 }
4442 }
4443 delete goodSample;
4444 }
4445}
4446
Note: See TracBrowser for help on using the repository browser.