source: drsdaq/DRS/DRS.cc@ 138

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