source: fact/drsdaq/DRS/DRS.cc@ 9882

Last change on this file since 9882 was 182, checked in by ogrimm, 15 years ago
Updates to DIM integration
File size: 212.3 KB
Line 
1/********************************************************************
2
3 Name: DRS.cpp
4 Created by: Stefan Ritt, Matthias Schneebeli
5
6 Contents: Library functions for DRS mezzanine and USB boards
7
8 $Id: DRS.cpp 14453 2009-10-22 10:51:29Z ritt $
9
10\********************************************************************/
11
12#include <stdio.h>
13#include <math.h>
14#include <string.h>
15#include <stdlib.h>
16#include <time.h>
17#include <assert.h>
18#include <algorithm>
19#include <sys/stat.h>
20#include "strlcpy.h"
21
22#ifdef CT_VME
23 #define MEM_SEGMENT 150000 // Size of the memory segment
24#endif
25
26#ifdef _MSC_VER
27#pragma warning(disable:4996)
28# include <windows.h>
29# include <direct.h>
30#else
31# include <unistd.h>
32# include <sys/time.h>
33inline void Sleep(useconds_t x)
34{
35 usleep(x * 1000);
36}
37#endif
38
39#ifdef _MSC_VER
40#include <conio.h>
41#define drs_kbhit() kbhit()
42#else
43#include <sys/ioctl.h>
44int drs_kbhit()
45{
46 int n;
47
48 ioctl(0, FIONREAD, &n);
49 return (n > 0);
50}
51static inline int getch()
52{
53 return getchar();
54}
55#endif
56
57#include <DRS.h>
58
59#ifdef _MSC_VER
60extern "C" {
61#endif
62
63#include <mxml.h>
64
65#ifdef _MSC_VER
66}
67#endif
68
69/*---- minimal FPGA firmvare version required for this library -----*/
70const int REQUIRED_FIRMWARE_VERSION_DRS2 = 5268;
71const int REQUIRED_FIRMWARE_VERSION_DRS3 = 6981;
72const int REQUIRED_FIRMWARE_VERSION_DRS4 = 13191;
73
74/*---- calibration methods to be stored in EEPROMs -----------------*/
75
76#define VCALIB_METHOD 1
77#define TCALIB_METHOD 1
78
79/*---- VME addresses -----------------------------------------------*/
80#if defined(HAVE_VME) || defined(CT_VME)
81
82/* assuming following DIP Switch settings:
83
84 SW1-1: 1 (off) use geographical addressing (1=left, 21=right)
85 SW1-2: 1 (off) \
86 SW1-3: 1 (off) > VME_WINSIZE = 8MB, subwindow = 1MB
87 SW1-4: 0 (on) /
88 SW1-5: 0 (on) reserverd
89 SW1-6: 0 (on) reserverd
90 SW1-7: 0 (on) reserverd
91 SW1-8: 0 (on) \
92 |
93 SW2-1: 0 (on) |
94 SW2-2: 0 (on) |
95 SW2-3: 0 (on) |
96 SW2-4: 0 (on) > VME_ADDR_OFFSET = 0
97 SW2-5: 0 (on) |
98 SW2-6: 0 (on) |
99 SW2-7: 0 (on) |
100 SW2-8: 0 (on) /
101
102 which gives
103 VME base address = SlotNo * VME_WINSIZE + VME_ADDR_OFFSET
104 = SlotNo * 0x80'0000
105*/
106#define GEVPC_BASE_ADDR 0x00000000
107#define GEVPC_WINSIZE 0x800000
108#define GEVPC_USER_FPGA (GEVPC_WINSIZE*2/8)
109#define PMC1_OFFSET 0x00000
110#define PMC2_OFFSET 0x80000
111#define PMC_CTRL_OFFSET 0x00000 /* all registers 32 bit */
112#define PMC_STATUS_OFFSET 0x10000
113#define PMC_FIFO_OFFSET 0x20000
114#define PMC_RAM_OFFSET 0x40000
115#endif // HAVE_VME
116/*---- USB addresses -----------------------------------------------*/
117#define USB_TIMEOUT 1000 // one second
118#ifdef HAVE_USB
119#define USB_CTRL_OFFSET 0x00 /* all registers 32 bit */
120#define USB_STATUS_OFFSET 0x40
121#define USB_RAM_OFFSET 0x80
122#define USB_CMD_IDENT 0 // Query identification
123#define USB_CMD_ADDR 1 // Address cycle
124#define USB_CMD_READ 2 // "VME" read <addr><size>
125#define USB_CMD_WRITE 3 // "VME" write <addr><size>
126#define USB_CMD_READ12 4 // 12-bit read <LSB><MSB>
127#define USB_CMD_WRITE12 5 // 12-bit write <LSB><MSB>
128
129#define USB2_CMD_READ 1
130#define USB2_CMD_WRITE 2
131#define USB2_CTRL_OFFSET 0x00000 /* all registers 32 bit */
132#define USB2_STATUS_OFFSET 0x10000
133#define USB2_FIFO_OFFSET 0x20000
134#define USB2_RAM_OFFSET 0x40000
135#endif // HAVE_USB
136
137/*------------------------------------------------------------------*/
138
139using namespace std;
140
141#ifdef HAVE_USB
142#define USB2_BUFFER_SIZE (1024*1024+10)
143unsigned char static *usb2_buffer = NULL;
144#endif
145
146/*------------------------------------------------------------------*/
147
148DRS::DRS()
149: fNumberOfBoards(0)
150#ifdef HAVE_VME
151 , fVmeInterface(0)
152#endif
153{
154#ifdef HAVE_USB
155 MUSB_INTERFACE *usb_interface;
156#endif
157
158 int index = 0, i = 0;
159 memset(fError, 0, sizeof(fError));
160
161#if defined(HAVE_VME) || defined(CT_VME)
162 unsigned short type, fw, magic, serial, temperature;
163
164#ifdef HAVE_VME
165 mvme_addr_t addr;
166
167 if (mvme_open(&fVmeInterface, 0) == MVME_SUCCESS) {
168 mvme_set_am(fVmeInterface, MVME_AM_A32);
169 mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
170#endif
171#ifdef CT_VME
172 unsigned int addr;
173
174 if (OpenVME() == VME_SUCCESS) {
175 if (OpenCMEM() != VME_SUCCESS) {
176 printf("Error with OpenCMEM()\n");
177 return;
178 }
179 // Set master mapping input information
180 MasterMap.window_size = GEVPC_WINSIZE;
181 MasterMap.address_modifier = VME_A32;
182 MasterMap.options = 0;
183#endif
184 /* check all VME slave slots */
185 for (index = 2; index <= 9; index++) {
186#ifdef CT_VME
187 MasterMap.vmebus_address = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
188 if (MasterMapVME(&MasterMapping[index]) != VME_SUCCESS) continue;
189#endif
190
191 /* check PMC1 and PMC2 */
192 for (int pmc=0; pmc<2; pmc++) {
193
194#ifdef HAVE_VME
195 addr = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE; // VME board base address
196 addr += GEVPC_USER_FPGA; // UsrFPGA base address
197 addr += (pmc == 0) ? PMC1_OFFSET : PMC2_OFFSET; // offset
198
199 mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
200 i = mvme_read(fVmeInterface, &magic, addr + PMC_STATUS_OFFSET + REG_MAGIC, 2);
201#endif
202#ifdef CT_VME
203 addr = 0; // VME board base address
204 addr += GEVPC_USER_FPGA; // UsrFPGA base address
205 addr += (pmc == 0) ? PMC1_OFFSET : PMC2_OFFSET; // offset
206 ErrorCode = VME_ReadSafeUShort(MasterMapping[index], addr + PMC_STATUS_OFFSET + REG_MAGIC, &magic);
207 if (ErrorCode == VME_SUCCESS) i = 2;
208 else i = 0;
209#endif
210 if (i == 2) {
211 if (magic != 0xC0DE) {
212 printf("Found old firmware, please upgrade immediately!\n");
213#ifdef HAVE_VME
214 fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1 | pmc);
215#endif
216#ifdef CT_VME
217 fBoard[fNumberOfBoards] = new DRSBoard(MasterMapping[index], MasterMap.vmebus_address, addr, (index-2) << 1 | pmc);
218#endif
219 fNumberOfBoards++;
220 } else {
221
222#ifdef HAVE_VME
223 /* read board type */
224 mvme_read(fVmeInterface, &type, addr + PMC_STATUS_OFFSET + REG_BOARD_TYPE, 2);
225 /* read firmware number */
226 mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);
227 /* read serial number */
228 mvme_read(fVmeInterface, &serial, addr + PMC_STATUS_OFFSET + REG_SERIAL_BOARD, 2);
229 /* read temperature register to see if CMC card is present */
230 mvme_read(fVmeInterface, &temperature, addr + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);
231
232#endif
233#ifdef CT_VME
234 /* read board type */
235 VME_ReadFastUShort(MasterMapping[index], addr + PMC_STATUS_OFFSET + REG_BOARD_TYPE, &type);
236 // Read firmware
237 VME_ReadFastUShort(MasterMapping[index], addr + PMC_STATUS_OFFSET + REG_VERSION_FW, &fw);
238 // Read serial number
239 VME_ReadFastUShort(MasterMapping[index], addr + PMC_STATUS_OFFSET + REG_SERIAL_BOARD, &serial);
240 // Read temperature register to see if CMC card is present
241 VME_ReadFastUShort(MasterMapping[index], addr + PMC_STATUS_OFFSET + REG_TEMPERATURE, &temperature);
242#endif
243 type &= 0xFF;
244 if (type == 2 || type == 3 || type == 4) { // DRS2 or DRS3 or DRS4
245 if (temperature == 0xFFFF) {
246 printf("Found VME board in slot %d, fw %d, but no CMC board in %s slot\n", index, fw, (pmc==0) ? "upper" : "lower");
247 }
248 else {
249 printf("Found DRS%d board %2d in %s VME slot %2d, serial #%d, firmware revision %d\n", type, fNumberOfBoards, (pmc==0) ? "upper" : "lower", index, serial, fw);
250
251#ifdef HAVE_VME
252 fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1 | pmc);
253#endif
254#ifdef CT_VME
255 fBoard[fNumberOfBoards] = new DRSBoard(MasterMapping[index], MasterMap.vmebus_address, addr, (index-2) << 1 | pmc);
256#endif
257 if (fBoard[fNumberOfBoards]->HasCorrectFirmware()) fNumberOfBoards++;
258 else {
259 sprintf(fError, "Wrong firmware version: board has %d, required is %d\n",
260 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
261 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
262 delete fBoard[fNumberOfBoards];
263 }
264 } // Temperature check
265 } // Type check
266 } // Magic check
267 }
268 } // pmc
269 }
270 } else printf("Cannot access VME crate, check driver, power and connection\n");
271#endif // HAVE_VME
272
273#ifdef HAVE_USB
274 unsigned char buffer[512];
275 int found, one_found, usb_slot;
276
277 one_found = 0;
278 usb_slot = 0;
279 for (index = 0; index < 127; index++) {
280 found = 0;
281
282 /* check for USB-Mezzanine test board */
283 if (musb_open(&usb_interface, 0x10C4, 0x1175, index, 1, 0) == MUSB_SUCCESS) {
284
285 /* check ID */
286 buffer[0] = USB_CMD_IDENT;
287 musb_write(usb_interface, 2, buffer, 1, USB_TIMEOUT);
288
289 i = musb_read(usb_interface, 1, (char *) buffer, sizeof(buffer), USB_TIMEOUT);
290 if (strcmp((char *) buffer, "USB_MEZZ2 V1.0") != 0) {
291 /* no USB-Mezzanine board found */
292 musb_close(usb_interface);
293 } else {
294 usb_interface->usb_type = 1; // USB 1.1
295 fBoard[fNumberOfBoards] = new DRSBoard(usb_interface, usb_slot++);
296 if (fBoard[fNumberOfBoards]->HasCorrectFirmware()) {
297 fNumberOfBoards++;
298 found = 1;
299 one_found = 1;
300 } else
301 sprintf(fError, "Wrong firmware version: board has %d, required is %d\n",
302 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
303 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
304 }
305 }
306
307 /* check for DRS4 evaluation board */
308 if (musb_open(&usb_interface, 0x04B4, 0x1175, index, 1, 0) == MUSB_SUCCESS) {
309
310 /* check ID */
311 struct usb_device_descriptor d;
312 usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d));
313 if (d.bcdDevice != 1) {
314 /* no DRS evaluation board found */
315 musb_close(usb_interface);
316 } else {
317
318 /* drain any data from Cy7C68013 FIFO if FPGA startup caused erratic write */
319 do {
320 i = musb_read(usb_interface, 8, buffer, sizeof(buffer), 100);
321 if (i > 0)
322 printf("%d bytes stuck in buffer\n", i);
323 } while (i > 0);
324
325 usb_interface->usb_type = 2; // USB 2.0
326 fBoard[fNumberOfBoards] = new DRSBoard(usb_interface, usb_slot++);
327 if (fBoard[fNumberOfBoards]->HasCorrectFirmware()) {
328 fNumberOfBoards++;
329 found = 1;
330 one_found = 1;
331 } else {
332 sprintf(fError, "Wrong firmware version: board has %d, required is %d\n",
333 fBoard[fNumberOfBoards]->GetFirmwareVersion(),
334 fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
335 }
336 }
337 }
338
339 if (!found) {
340 if (!one_found)
341 printf("USB successfully scanned, but no boards found\n");
342 break;
343 }
344 }
345#endif // HAVE_USB
346
347 return;
348}
349
350/*------------------------------------------------------------------*/
351
352DRS::~DRS()
353{
354 int i;
355 for (i = 0; i < fNumberOfBoards; i++) {
356 delete fBoard[i];
357 }
358
359#ifdef HAVE_USB
360 if (usb2_buffer) {
361 free(usb2_buffer);
362 usb2_buffer = NULL;
363 }
364#endif
365
366#ifdef HAVE_VME
367 mvme_close(fVmeInterface);
368#endif
369
370#ifdef CT_VME
371 if (CloseVME() != VME_SUCCESS) printf("Error with CloseVME()\n");
372 if (CloseCMEM()!= VME_SUCCESS) printf("Error with CloseCMEM()\n");
373#endif
374}
375
376/*------------------------------------------------------------------*/
377
378bool DRS::GetError(char *str, int size)
379{
380 if (fError[0])
381 strlcpy(str, fError, size);
382
383 return fError[0] > 0;
384}
385
386/*------------------------------------------------------------------*/
387
388#ifdef HAVE_USB
389DRSBoard::DRSBoard(MUSB_INTERFACE * musb_interface, int usb_slot)
390: fDAC_COFSA(0)
391 , fDAC_COFSB(0)
392 , fDAC_DRA(0)
393 , fDAC_DSA(0)
394 , fDAC_TLEVEL(0)
395 , fDAC_ACALIB(0)
396 , fDAC_DSB(0)
397 , fDAC_DRB(0)
398 , fDAC_COFS(0)
399 , fDAC_ADCOFS(0)
400 , fDAC_CLKOFS(0)
401 , fDAC_ROFS_1(0)
402 , fDAC_ROFS_2(0)
403 , fDAC_INOFS(0)
404 , fDAC_BIAS(0)
405 , fDRSType(0)
406 , fBoardType(0)
407 , fRequiredFirmwareVersion(0)
408 , fFirmwareVersion(0)
409 , fBoardSerialNumber(0)
410 , fCtrlBits(0)
411 , fNumberOfReadoutChannels(0)
412 , fReadoutChannelConfig(0)
413 , fADCClkPhase(0)
414 , fADCClkInvert(0)
415 , fExternalClockFrequency(0)
416 , fUsbInterface(musb_interface)
417#ifdef HAVE_VME
418 , fVmeInterface(0)
419 , fBaseAddress(0)
420#endif
421 , fSlotNumber(usb_slot)
422 , fFrequency(0)
423 , fDominoMode(0)
424 , fDominoActive(0)
425 , fChannelConfig(0)
426 , fWSRLoop(0)
427 , fReadoutMode(0)
428 , fTriggerEnable1(0)
429 , fTriggerEnable2(0)
430 , fTriggerSource(0)
431 , fTriggerDelay(0)
432 , fDelayedStart(0)
433 , fRange(0)
434 , fCommonMode(0.8)
435 , fAcalMode(0)
436 , fAcalVolt(0)
437 , fTcalFreq(0)
438 , fTcalLevel(0)
439 , fTcalPhase(0)
440 , fMaxChips(0)
441 , fResponseCalibration(0)
442 , fCellCalibrationValid(false)
443 , fCellCalibratedRange(0)
444 , fTimingCalibrationValid(false)
445 , fTimeData(0)
446 , fNumberOfTimeData(0)
447 , fDebug(0)
448 , fTriggerStartBin(0)
449{
450 if (musb_interface->usb_type == 1)
451 fTransport = TR_USB;
452 else
453 fTransport = TR_USB2;
454 memset(fStopCell, 0, sizeof(fStopCell));
455 ConstructBoard();
456}
457
458#endif
459
460#ifdef HAVE_VME
461/*------------------------------------------------------------------*/
462
463DRSBoard::DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number)
464:fDAC_COFSA(0)
465, fDAC_COFSB(0)
466, fDAC_DRA(0)
467, fDAC_DSA(0)
468, fDAC_TLEVEL(0)
469, fDAC_ACALIB(0)
470, fDAC_DSB(0)
471, fDAC_DRB(0)
472, fDAC_COFS(0)
473, fDAC_ADCOFS(0)
474, fDAC_CLKOFS(0)
475, fDAC_ROFS_1(0)
476, fDAC_ROFS_2(0)
477, fDAC_INOFS(0)
478, fDAC_BIAS(0)
479, fDRSType(0)
480, fBoardType(0)
481, fRequiredFirmwareVersion(0)
482, fFirmwareVersion(0)
483, fBoardSerialNumber(0)
484, fTransport(TR_VME)
485, fCtrlBits(0)
486, fNumberOfReadoutChannels(0)
487, fReadoutChannelConfig(0)
488, fADCClkPhase(0)
489, fADCClkInvert(0)
490, fExternalClockFrequency(0)
491#ifdef HAVE_USB
492, fUsbInterface(0)
493#endif
494#ifdef HAVE_VME
495, fVmeInterface(mvme_interface)
496, fBaseAddress(base_address)
497, fSlotNumber(slot_number)
498#endif
499, fFrequency(0)
500, fRefClock(0)
501, fDominoMode(1)
502, fDominoActive(1)
503, fChannelConfig(0)
504, fWSRLoop(1)
505, fReadoutMode(0)
506, fTriggerEnable1(0)
507, fTriggerEnable2(0)
508, fTriggerSource(0)
509, fTriggerDelay(0)
510, fDelayedStart(0)
511, fRange(0)
512, fCommonMode(0.8)
513, fAcalMode(0)
514, fAcalVolt(0)
515, fTcalFreq(0)
516, fTcalLevel(0)
517, fTcalPhase(0)
518, fMaxChips(0)
519, fResponseCalibration(0)
520, fTimeData(0)
521, fNumberOfTimeData(0)
522, fDebug(0)
523, fTriggerStartBin(0)
524{
525 ConstructBoard();
526}
527
528#endif
529
530#ifdef CT_VME
531/*------------------------------------------------------------------*/
532
533DRSBoard::DRSBoard(int MasterMapping, unsigned int base_address, unsigned int BoardAddress, int slot_number)
534:fDAC_COFSA(0)
535, fDAC_COFSB(0)
536, fDAC_DRA(0)
537, fDAC_DSA(0)
538, fDAC_TLEVEL(0)
539, fDAC_ACALIB(0)
540, fDAC_DSB(0)
541, fDAC_DRB(0)
542, fDAC_COFS(0)
543, fDAC_ADCOFS(0)
544, fDAC_CLKOFS(0)
545, fDAC_ROFS_1(0)
546, fDAC_ROFS_2(0)
547, fDAC_INOFS(0)
548, fDAC_BIAS(0)
549, fDRSType(0)
550, fBoardType(0)
551, fRequiredFirmwareVersion(0)
552, fFirmwareVersion(0)
553, fBoardSerialNumber(0)
554, fTransport(TR_VME)
555, fCtrlBits(0)
556, fNumberOfReadoutChannels(0)
557, fReadoutChannelConfig(0)
558, fADCClkPhase(0)
559, fADCClkInvert(0)
560, fExternalClockFrequency(0)
561, fBaseAddress(base_address)
562, fBoardAddress(BoardAddress)
563, fMasterMapping(MasterMapping)
564, fSlotNumber(slot_number)
565, fFrequency(0)
566, fRefClock(0)
567, fDominoMode(1)
568, fDominoActive(1)
569, fChannelConfig(0)
570, fWSRLoop(1)
571, fReadoutMode(0)
572, fTriggerEnable1(0)
573, fTriggerEnable2(0)
574, fTriggerSource(0)
575, fTriggerDelay(0)
576, fDelayedStart(0)
577, fRange(0)
578, fCommonMode(0.8)
579, fAcalMode(0)
580, fAcalVolt(0)
581, fTcalFreq(0)
582, fTcalLevel(0)
583, fTcalPhase(0)
584, fMaxChips(0)
585, fResponseCalibration(0)
586, fTimeData(0)
587, fNumberOfTimeData(0)
588, fDebug(0)
589, fTriggerStartBin(0)
590{
591 // Allocate contiguous memory for BLT
592 AllocateSegmentCMEM(MEM_SEGMENT,&CMEM_SegIdentifier);
593 AssignPhysicalSegAddressCMEM(CMEM_SegIdentifier, &PCIAddress);
594 AssignVirtualSegAddressCMEM(CMEM_SegIdentifier, &VirtualAddress);
595 ConstructBoard();
596}
597#endif
598
599/*------------------------------------------------------------------*/
600
601DRSBoard::~DRSBoard()
602{
603 int i;
604#ifdef HAVE_USB
605 if (fTransport == TR_USB || fTransport == TR_USB2)
606 musb_close(fUsbInterface);
607#endif
608
609 // Response Calibration
610 delete fResponseCalibration;
611
612 // Time Calibration
613 for (i = 0; i < fNumberOfTimeData; i++) {
614 delete fTimeData[i];
615 }
616 delete[]fTimeData;
617
618#ifdef CT_VME
619 FreeSegmentCMEM(CMEM_SegIdentifier);
620#endif
621
622}
623
624/*------------------------------------------------------------------*/
625
626void DRSBoard::ConstructBoard()
627{
628 unsigned char buffer[2];
629
630 fDebug = 0;
631 fWSRLoop = 1;
632 fCtrlBits = 0;
633
634 fExternalClockFrequency = 1000. / 30.;
635 strcpy(fCalibDirectory, ".");
636
637 /* check board communication */
638 if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0) {
639 InitFPGA();
640 if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0)
641 return;
642 }
643
644 ReadSerialNumber();
645
646 /* check for required firmware version */
647 if (!HasCorrectFirmware())
648 return;
649
650 /* set correct reference clock */
651 if (fBoardType == 5)
652 fRefClock = 60;
653 else
654 fRefClock = 33;
655
656 /* get mode from hardware */
657 if (fDRSType == 4) {
658 fDominoMode = (GetConfigReg() & BIT_CONFIG_DMODE) > 0;
659 } else {
660 fDominoMode = (GetCtrlReg() & BIT_DMODE) > 0;
661 }
662 fTriggerEnable1 = (GetConfigReg() & BIT_ENABLE_TRIGGER1) > 0;
663 fTriggerEnable2 = (GetConfigReg() & BIT_ENABLE_TRIGGER2) > 0;
664 fTriggerSource = ((GetConfigReg() & BIT_TR_SOURCE1) > 0) | (((GetConfigReg() & BIT_TR_SOURCE2) > 0) << 1);
665 fReadoutMode = (GetConfigReg() & BIT_READOUT_MODE) > 0;
666 fADCClkInvert = (GetConfigReg() & BIT_ADCCLK_INVERT) > 0;
667 fDominoActive = (GetConfigReg() & BIT_DACTIVE) > 0;
668 ReadFrequency(0, &fFrequency);
669 if (fFrequency < 0.1 || fFrequency > 6)
670 fFrequency = 1;
671
672 /* initialize number of channels */
673 if (fDRSType == 4) {
674 if (fBoardType == 6) {
675 unsigned short d;
676 Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
677 fReadoutChannelConfig = d & 0xFF;
678 if (d == 7)
679 fNumberOfReadoutChannels = 9;
680 else
681 fNumberOfReadoutChannels = 5;
682 } else
683 fNumberOfReadoutChannels = 9;
684 } else
685 fNumberOfReadoutChannels = 10;
686
687 if (fBoardType == 1) {
688 fDAC_COFSA = 0;
689 fDAC_COFSB = 1;
690 fDAC_DRA = 2;
691 fDAC_DSA = 3;
692 fDAC_TLEVEL = 4;
693 fDAC_ACALIB = 5;
694 fDAC_DSB = 6;
695 fDAC_DRB = 7;
696 } else if (fBoardType == 2 || fBoardType == 3) {
697 fDAC_COFS = 0;
698 fDAC_DSA = 1;
699 fDAC_DSB = 2;
700 fDAC_TLEVEL = 3;
701 fDAC_CLKOFS = 5;
702 fDAC_ACALIB = 6;
703 fDAC_ADCOFS = 7;
704 } else if (fBoardType == 4) {
705 fDAC_ROFS_1 = 0;
706 fDAC_DSA = 1;
707 fDAC_DSB = 2;
708 fDAC_ROFS_2 = 3;
709 fDAC_BIAS = 4;
710 fDAC_INOFS = 5;
711 fDAC_ACALIB = 6;
712 fDAC_ADCOFS = 7;
713 } else if (fBoardType == 5) {
714 fDAC_ROFS_1 = 0;
715 fDAC_CMOFS = 1;
716 fDAC_CALN = 2;
717 fDAC_CALP = 3;
718 fDAC_BIAS = 4;
719 fDAC_TLEVEL = 5;
720 fDAC_ONOFS = 6;
721 } else if (fBoardType == 6) {
722 fDAC_ONOFS = 0;
723 fDAC_CMOFSP = 1;
724 fDAC_CALN = 2;
725 fDAC_CALP = 3;
726 fDAC_CMOFSN = 5;
727 fDAC_ROFS_1 = 6;
728 fDAC_BIAS = 7;
729 }
730
731 if (fDRSType == 4) {
732 ReadCalibration();
733 } else {
734 // Response Calibration
735 fResponseCalibration = new ResponseCalibration(this);
736
737 // Time Calibration
738 fTimeData = new DRSBoard::TimeData *[kNumberOfChipsMax];
739 fNumberOfTimeData = 0;
740 }
741}
742
743/*------------------------------------------------------------------*/
744
745void DRSBoard::ReadSerialNumber()
746{
747 unsigned char buffer[2];
748 int number;
749
750 // check magic number
751 if (Read(T_STATUS, buffer, REG_MAGIC, 2) < 0) {
752 printf("Cannot read from board\n");
753 return;
754 }
755
756 number = (static_cast < int >(buffer[1]) << 8) +buffer[0];
757 if (number != 0xC0DE) {
758 printf("Invalid magic number: %04X\n", number);
759 return;
760 }
761
762 // read board type
763 Read(T_STATUS, buffer, REG_BOARD_TYPE, 2);
764 fDRSType = buffer[0];
765 fBoardType = buffer[1];
766
767 // read firmware version
768 Read(T_STATUS, buffer, REG_VERSION_FW, 2);
769 fFirmwareVersion = (static_cast < int >(buffer[1]) << 8) +buffer[0];
770
771 // retrieve board serial number
772 Read(T_STATUS, buffer, REG_SERIAL_BOARD, 2);
773 number = (static_cast < int >(buffer[1]) << 8) +buffer[0];
774 fBoardSerialNumber = number;
775
776 // determine DRS type and board type for old boards from setial number
777 if (fBoardType == 0) {
778 // determine board version from serial number
779 if (number >= 2000 && number < 5000) {
780 fBoardType = 6;
781 fDRSType = 4;
782 } else if (number >= 1000) {
783 fBoardType = 4;
784 fDRSType = 3;
785 } else if (number >= 100)
786 fBoardType = 3;
787 else if (number > 0)
788 fBoardType = 2;
789 else {
790 fBoardType = 3;
791 fDRSType = 2;
792 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
793 }
794 }
795
796 // set constants according to board type
797 if (fBoardType == 6)
798 fNumberOfChips = 4;
799 else
800 fNumberOfChips = 2;
801
802 if (fDRSType == 4)
803 fNumberOfChannels = 9;
804 else
805 fNumberOfChannels = 10;
806
807 // retrieve firmware version
808 if (fDRSType == 2)
809 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS2;
810 if (fDRSType == 3)
811 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS3;
812 if (fDRSType == 4)
813 fRequiredFirmwareVersion = REQUIRED_FIRMWARE_VERSION_DRS4;
814
815}
816
817/*------------------------------------------------------------------*/
818
819void DRSBoard::ReadCalibration(void)
820{
821 unsigned short buf[1024*9*2];
822 int i, j, chip;
823
824 fCellCalibrationValid = false;
825 fTimingCalibrationValid = false;
826
827 memset(fCellOffset, 0, sizeof(fCellOffset));
828 memset(fCellGain, 0, sizeof(fCellGain));
829 memset(fCellOffset2, 0, sizeof(fCellOffset2));
830 memset(fCellT, 0, sizeof(fCellT));
831
832 /* read offsets and gain from eeprom */
833 if (fBoardType == 5) {
834 ReadEEPROM(0, buf, 16);
835
836 /* check voltage calibration method */
837 if ((buf[2] & 0xFF) == VCALIB_METHOD)
838 fCellCalibrationValid = true;
839 else {
840 fCellCalibratedRange = 0;
841 return;
842 }
843
844 /* check timing calibration method */
845 if ((buf[4] & 0xFF) == TCALIB_METHOD)
846 fTimingCalibrationValid = true;
847 else {
848 fTimingCalibratedFrequency = 0;
849 }
850
851 fCellCalibratedRange = ((int) (buf[2] >> 8)) / 100.0; // -50 ... +50 => -0.5 V ... +0.5 V
852 fTimingCalibratedFrequency = buf[6] / 65525.0 * 6; // 0 ... 65535 => 0 ... 6 GHz
853
854 ReadEEPROM(1, buf, 1024*32);
855 for (i=0 ; i<8 ; i++)
856 for (j=0 ; j<1024; j++) {
857 fCellOffset[i][j] = buf[(i*1024+j)*2];
858 fCellGain[i][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
859 }
860
861 ReadEEPROM(2, buf, 1024*5*4);
862 for (i=0 ; i<1 ; i++)
863 for (j=0 ; j<1024; j++) {
864 fCellOffset[i+8][j] = buf[(i*1024+j)*2];
865 fCellGain[i+8][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
866 }
867
868 for (i=0 ; i<4 ; i++)
869 for (j=0 ; j<1024; j++) {
870 fCellOffset2[i*2][j] = buf[2*1024+((i*2)*1024+j)*2];
871 fCellOffset2[i*2+1][j] = buf[2*1024+((i*2)*1024+j)*2+1];
872 }
873
874 } else if (fBoardType == 6) {
875 ReadEEPROM(0, buf, 16);
876
877 /* check voltage calibration method */
878 if ((buf[2] & 0xFF) == VCALIB_METHOD)
879 fCellCalibrationValid = true;
880 else {
881 fCellCalibratedRange = 0;
882 return;
883 }
884
885 /* check timing calibration method */
886 if ((buf[4] & 0xFF) == TCALIB_METHOD)
887 fTimingCalibrationValid = true;
888 else {
889 fTimingCalibratedFrequency = 0;
890 }
891
892 fCellCalibratedRange = ((int) (buf[2] >> 8)) / 100.0; // -50 ... +50 => -0.5 V ... +0.5 V
893 fTimingCalibratedFrequency = buf[6] / 65525.0 * 6; // 0 ... 65535 => 0 ... 6 GHz
894
895 for (chip=0 ; chip<4 ; chip++) {
896 ReadEEPROM(1+chip, buf, 1024*32);
897 for (i=0 ; i<8 ; i++)
898 for (j=0 ; j<1024; j++) {
899 fCellOffset[i+chip*9][j] = buf[(i*1024+j)*2];
900 fCellGain[i+chip*9][j] = buf[(i*1024+j)*2 + 1]/65535.0*0.4+0.7;
901 }
902 }
903
904 ReadEEPROM(5, buf, 1024*4*4);
905 for (chip=0 ; chip<4 ; chip++)
906 for (j=0 ; j<1024; j++) {
907 fCellOffset[8+chip*9][j] = buf[j*2+chip*0x0800];
908 fCellGain[8+chip*9][j] = buf[j*2+1+chip*0x0800]/65535.0*0.4+0.7;
909 }
910
911 ReadEEPROM(7, buf, 1024*32);
912 for (i=0 ; i<8 ; i++) {
913 for (j=0 ; j<1024; j++) {
914 fCellOffset2[i][j] = buf[i*0x800 + j*2];
915 fCellOffset2[i+9][j] = buf[i*0x800 + j*2+1];
916 }
917 }
918
919 ReadEEPROM(8, buf, 1024*32);
920 for (i=0 ; i<8 ; i++) {
921 for (j=0 ; j<1024; j++) {
922 fCellOffset2[i+18][j] = buf[i*0x800 + j*2];
923 fCellOffset2[i+27][j] = buf[i*0x800 + j*2+1];
924 }
925 }
926
927 }
928 else return;
929
930 /* read timing calibration from eeprom */
931 if (fBoardType == 5) {
932 if (!fTimingCalibrationValid) {
933 for (i=0 ; i<1024 ; i++)
934 fCellT[0][i] = 1/fFrequency*i;
935 } else {
936 ReadEEPROM(0, buf, 1024*sizeof(short)*2);
937 fCellT[0][0] = 0;
938 for (i=1 ; i<1024; i++)
939 fCellT[0][i] = fCellT[0][i-1] + buf[i*2+1]/10000.0;
940 }
941 } else if (fBoardType == 6) {
942 if (!fTimingCalibrationValid) {
943 for (i=0 ; i<1024 ; i++)
944 for (j=0 ; j<4 ; j++)
945 fCellT[j][i] = 1/fFrequency*i;
946 } else {
947 ReadEEPROM(6, buf, 1024*sizeof(short)*4);
948 for (j=0 ; j<4 ; j++)
949 fCellT[j][0] = 0;
950 for (i=1 ; i<1024; i++) {
951 fCellT[0][i] = fCellT[0][i-1] + buf[i*2]/10000.0;
952 fCellT[1][i] = fCellT[1][i-1] + buf[i*2+1]/10000.0;
953 fCellT[2][i] = fCellT[2][i-1] + buf[i*2+0x800]/10000.0;
954 fCellT[3][i] = fCellT[3][i-1] + buf[i*2+0x800+1]/10000.0;
955 }
956 }
957 }
958}
959
960/*------------------------------------------------------------------*/
961
962bool DRSBoard::HasCorrectFirmware()
963{
964 /* check for required firmware version */
965 return (fFirmwareVersion >= fRequiredFirmwareVersion);
966}
967
968/*------------------------------------------------------------------*/
969
970int DRSBoard::InitFPGA(void)
971{
972
973#ifdef HAVE_USB
974 if (fTransport == TR_USB2) {
975 unsigned char buffer[1];
976 int i, status;
977
978 /* blink Cy7C68013A LED and issue an FPGA reset */
979 buffer[0] = 0; // LED off
980 musb_write(fUsbInterface, 1, buffer, 1, 100);
981 Sleep(50);
982
983 buffer[0] = 1; // LED on
984 musb_write(fUsbInterface, 1, buffer, 1, 100);
985
986 /* wait until EEPROM page #0 has been read */
987 for (i=0 ; i<100 ; i++) {
988 Read(T_STATUS, &status, REG_STATUS, 4);
989 if ((status & BIT_SERIAL_BUSY) == 0)
990 break;
991 Sleep(10);
992 }
993 }
994#endif
995
996 return 1;
997}
998
999int DRSBoard::Write(int type, unsigned int addr, void *data, int size)
1000{
1001 // Generic write function
1002
1003#ifdef CT_VME
1004 if (size > MEM_SEGMENT) size = MEM_SEGMENT;
1005
1006 if (type == T_CTRL) addr += PMC_CTRL_OFFSET;
1007 else if (type == T_STATUS) addr += PMC_STATUS_OFFSET;
1008 else if (type == T_RAM) addr += PMC_RAM_OFFSET;
1009 else return 0;
1010
1011 if (size == 1) {
1012 ErrorCode = VME_WriteSafeUChar(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned char*>(data)));
1013 }
1014 else if (size == 2) {
1015 ErrorCode = VME_WriteSafeUShort(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned short*>(data)));
1016 }
1017 else if (size == 4) {
1018 ErrorCode = VME_WriteSafeUInt(fMasterMapping, fBoardAddress + addr, *(static_cast<unsigned int*>(data)));
1019 }
1020 else {
1021 // Copy to contiguous block of memory at VirtualAddress
1022 memcpy((void *) VirtualAddress, data, size);
1023
1024 // Assign fields for BLT and perform BLT
1025 BLT_List.list_of_items[0].vmebus_address = fBaseAddress + fBoardAddress + PMC_RAM_OFFSET;
1026 BLT_List.list_of_items[0].system_iobus_address = PCIAddress;
1027 BLT_List.list_of_items[0].size_requested = size;
1028 BLT_List.list_of_items[0].control_word = VME_DMA_D64W | VME_A32;
1029 BLT_List.number_of_items = 1;
1030 ErrorCode = VME_BlockTransfer(&BLT_List,-1);
1031 }
1032 if (ErrorCode != VME_SUCCESS) {
1033 VME_ErrorPrint(ErrorCode);
1034 return 0;
1035 }
1036 else return size;
1037#endif
1038
1039 if (fTransport == TR_VME) {
1040
1041#ifdef HAVE_VME
1042 unsigned int base_addr;
1043
1044 base_addr = fBaseAddress;
1045
1046 if (type == T_CTRL)
1047 base_addr += PMC_CTRL_OFFSET;
1048 else if (type == T_STATUS)
1049 base_addr += PMC_STATUS_OFFSET;
1050 else if (type == T_RAM)
1051 base_addr += PMC_RAM_OFFSET;
1052
1053 if (size == 1) {
1054 /* 8-bit write access */
1055 mvme_set_dmode(fVmeInterface, MVME_DMODE_D8);
1056 mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
1057 } else if (size == 2) {
1058 /* 16-bit write access */
1059 mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
1060 mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
1061 } else {
1062 mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
1063
1064 /* as long as no block transfer is supported, do pseudo block transfer */
1065 mvme_set_blt(fVmeInterface, MVME_BLT_NONE);
1066
1067 mvme_write(fVmeInterface, base_addr + addr, static_cast < mvme_locaddr_t * >(data), size);
1068 }
1069
1070 return size;
1071#endif // HAVE_VME
1072
1073 } else if (fTransport == TR_USB) {
1074#ifdef HAVE_USB
1075 unsigned char buffer[64], ack;
1076 unsigned int base_addr;
1077 int i, j, n;
1078
1079 if (type == T_CTRL)
1080 base_addr = USB_CTRL_OFFSET;
1081 else if (type == T_STATUS)
1082 base_addr = USB_STATUS_OFFSET;
1083 else if (type == T_RAM)
1084 base_addr = USB_RAM_OFFSET;
1085 else
1086 base_addr = 0;
1087
1088 if (type != T_RAM) {
1089
1090 /*---- register access ----*/
1091
1092 if (size == 2) {
1093 /* word swapping: first 16 bit sit at upper address */
1094 if ((addr % 4) == 0)
1095 addr = addr + 2;
1096 else
1097 addr = addr - 2;
1098 }
1099
1100 buffer[0] = USB_CMD_WRITE;
1101 buffer[1] = base_addr + addr;
1102 buffer[2] = size;
1103
1104 for (i = 0; i < size; i++)
1105 buffer[3 + i] = *((unsigned char *) data + i);
1106
1107 /* try 10 times */
1108 ack = 0;
1109 for (i = 0; i < 10; i++) {
1110 n = musb_write(fUsbInterface, 2, buffer, 3 + size, USB_TIMEOUT);
1111 if (n == 3 + size) {
1112 for (j = 0; j < 10; j++) {
1113 /* wait for acknowledge */
1114 n = musb_read(fUsbInterface, 1, &ack, 1, USB_TIMEOUT);
1115 if (n == 1 && ack == 1)
1116 break;
1117
1118 printf("Redo receive\n");
1119 }
1120 }
1121
1122 if (ack == 1)
1123 return size;
1124
1125 printf("Redo send\n");
1126 }
1127 } else {
1128
1129 /*---- RAM access ----*/
1130
1131 buffer[0] = USB_CMD_ADDR;
1132 buffer[1] = base_addr + addr;
1133 musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
1134
1135 /* chop buffer into 60-byte packets */
1136 for (i = 0; i <= (size - 1) / 60; i++) {
1137 n = size - i * 60;
1138 if (n > 60)
1139 n = 60;
1140 buffer[0] = USB_CMD_WRITE12;
1141 buffer[1] = n;
1142
1143 for (j = 0; j < n; j++)
1144 buffer[2 + j] = *((unsigned char *) data + j + i * 60);
1145
1146 musb_write(fUsbInterface, 2, buffer, 2 + n, USB_TIMEOUT);
1147
1148 for (j = 0; j < 10; j++) {
1149 /* wait for acknowledge */
1150 n = musb_read(fUsbInterface, 1, &ack, 1, USB_TIMEOUT);
1151 if (n == 1 && ack == 1)
1152 break;
1153
1154 printf("Redo receive acknowledge\n");
1155 }
1156 }
1157
1158 return size;
1159 }
1160#endif // HAVE_USB
1161 } else if (fTransport == TR_USB2) {
1162#ifdef HAVE_USB
1163 unsigned int base_addr;
1164 int i;
1165
1166 if (usb2_buffer == NULL)
1167 usb2_buffer = (unsigned char *) malloc(USB2_BUFFER_SIZE);
1168 assert(usb2_buffer);
1169
1170 /* only accept even address and number of bytes */
1171 assert(addr % 2 == 0);
1172 assert(size % 2 == 0);
1173
1174 /* check for maximum size */
1175 assert(size <= USB2_BUFFER_SIZE - 10);
1176
1177 if (type == T_CTRL)
1178 base_addr = USB2_CTRL_OFFSET;
1179 else if (type == T_STATUS)
1180 base_addr = USB2_STATUS_OFFSET;
1181 else if (type == T_FIFO)
1182 base_addr = USB2_FIFO_OFFSET;
1183 else if (type == T_RAM)
1184 base_addr = USB2_RAM_OFFSET;
1185 else
1186 base_addr = 0;
1187
1188 if (type != T_RAM && size == 2) {
1189 /* word swapping: first 16 bit sit at upper address */
1190 if ((addr % 4) == 0)
1191 addr = addr + 2;
1192 else
1193 addr = addr - 2;
1194 }
1195
1196 addr += base_addr;
1197
1198 usb2_buffer[0] = USB2_CMD_WRITE;
1199 usb2_buffer[1] = 0;
1200
1201 usb2_buffer[2] = (addr >> 0) & 0xFF;
1202 usb2_buffer[3] = (addr >> 8) & 0xFF;
1203 usb2_buffer[4] = (addr >> 16) & 0xFF;
1204 usb2_buffer[5] = (addr >> 24) & 0xFF;
1205
1206 usb2_buffer[6] = (size >> 0) & 0xFF;
1207 usb2_buffer[7] = (size >> 8) & 0xFF;
1208 usb2_buffer[8] = (size >> 16) & 0xFF;
1209 usb2_buffer[9] = (size >> 24) & 0xFF;
1210
1211 for (i = 0; i < size; i++)
1212 usb2_buffer[10 + i] = *((unsigned char *) data + i);
1213
1214 i = musb_write(fUsbInterface, 4, usb2_buffer, 10 + size, USB_TIMEOUT);
1215 if (i != 10 + size)
1216 printf("musb_write error: %d\n", i);
1217
1218 return i;
1219#endif // HAVE_USB
1220 }
1221
1222 return 0;
1223}
1224
1225/*------------------------------------------------------------------*/
1226
1227int DRSBoard::Read(int type, void *data, unsigned int addr, int size)
1228{
1229 // Generic read function
1230
1231#ifdef CT_VME
1232 if (size > MEM_SEGMENT) size = MEM_SEGMENT;
1233
1234 if (type == T_CTRL) addr += PMC_CTRL_OFFSET;
1235 else if (type == T_STATUS) addr += PMC_STATUS_OFFSET;
1236 else if (type == T_RAM) addr += PMC_RAM_OFFSET;
1237 else if (type == T_FIFO) addr += PMC_FIFO_OFFSET;
1238 else return 0;
1239
1240 if (size == 1) {
1241 ErrorCode = VME_ReadSafeUChar(fMasterMapping, fBoardAddress + addr, static_cast<unsigned char*>(data));
1242 } else if (size == 2) {
1243 ErrorCode = VME_ReadSafeUShort(fMasterMapping, fBoardAddress + addr, static_cast<unsigned short*>(data));
1244 } else if (size == 4) {
1245 ErrorCode = VME_ReadSafeUInt(fMasterMapping, fBoardAddress + addr, static_cast<unsigned int*>(data));
1246 } else {
1247
1248 // Assign fields and perform BLT
1249 BLT_List.list_of_items[0].vmebus_address = fBaseAddress + fBoardAddress + PMC_RAM_OFFSET;
1250 BLT_List.list_of_items[0].system_iobus_address = PCIAddress;
1251 BLT_List.list_of_items[0].size_requested = size;
1252 BLT_List.list_of_items[0].control_word = VME_DMA_D64R | VME_A32;
1253 BLT_List.number_of_items = 1;
1254 ErrorCode = VME_BlockTransfer(&BLT_List, -1);
1255
1256 // Copy contiguous block of memory starting from VirtualAddress
1257 memcpy(data, (void *) VirtualAddress, size);
1258 }
1259
1260 if (ErrorCode != VME_SUCCESS) {
1261 VME_ErrorPrint(ErrorCode);
1262 return 0;
1263 }
1264 else return size;
1265#endif
1266
1267 if (fTransport == TR_VME) {
1268
1269#ifdef HAVE_VME
1270 unsigned int base_addr;
1271 int n, i;
1272
1273 base_addr = fBaseAddress;
1274
1275 if (type == T_CTRL)
1276 base_addr += PMC_CTRL_OFFSET;
1277 else if (type == T_STATUS)
1278 base_addr += PMC_STATUS_OFFSET;
1279 else if (type == T_RAM)
1280 base_addr += PMC_RAM_OFFSET;
1281 else if (type == T_FIFO)
1282 base_addr += PMC_FIFO_OFFSET;
1283
1284 mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
1285
1286 n = 0;
1287 if (size == 1) {
1288 /* 8-bit read access */
1289 mvme_set_dmode(fVmeInterface, MVME_DMODE_D8);
1290 n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
1291 } else if (size == 2) {
1292 /* 16-bit read access */
1293 mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
1294 n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
1295 } else {
1296 mvme_set_dmode(fVmeInterface, MVME_DMODE_D32);
1297
1298 //mvme_set_blt(fVmeInterface, MVME_BLT_NONE); // pseudo block transfer
1299 mvme_set_blt(fVmeInterface, MVME_BLT_2EVME); // 2eVME if implemented
1300 n = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data), base_addr + addr, size);
1301 while (n != size) {
1302 printf("Only read %d out of %d, retry with %d: ", n, size, size - n);
1303 i = mvme_read(fVmeInterface, static_cast < mvme_locaddr_t * >(data) + n / 4, base_addr + addr + n,
1304 size - n);
1305 printf("read %d\n", i);
1306 if (i == 0) {
1307 printf("Error reading VME\n");
1308 return n;
1309 }
1310 n += i;
1311 }
1312
1313 //for (i = 0; i < size; i += 4)
1314 // mvme_read(fVmeInterface, (mvme_locaddr_t *)((char *)data+i), base_addr + addr+i, 4);
1315 }
1316 return n;
1317
1318#endif // HAVE_VME
1319 } else if (fTransport == TR_USB) {
1320#ifdef HAVE_USB
1321 unsigned char buffer[64];
1322 unsigned int base_addr;
1323 int i, j, ret, n;
1324
1325 if (type == T_CTRL)
1326 base_addr = USB_CTRL_OFFSET;
1327 else if (type == T_STATUS)
1328 base_addr = USB_STATUS_OFFSET;
1329 else if (type == T_RAM)
1330 base_addr = USB_RAM_OFFSET;
1331 else
1332 assert(0); // FIFO not implemented
1333
1334 if (type != T_RAM) {
1335
1336 /*---- register access ----*/
1337
1338 if (size == 2) {
1339 /* word swapping: first 16 bit sit at uppder address */
1340 if ((addr % 4) == 0)
1341 addr = addr + 2;
1342 else
1343 addr = addr - 2;
1344 }
1345
1346 buffer[0] = USB_CMD_READ;
1347 buffer[1] = base_addr + addr;
1348 buffer[2] = size;
1349
1350 musb_write(fUsbInterface, 2, buffer, 2 + size, USB_TIMEOUT);
1351 i = musb_read(fUsbInterface, 1, data, size, USB_TIMEOUT);
1352
1353 if (i != size)
1354 return 0;
1355
1356 return size;
1357 } else {
1358
1359 /*---- RAM access ----*/
1360
1361 /* in RAM mode, only the 2048-byte page can be selected */
1362 buffer[0] = USB_CMD_ADDR;
1363 buffer[1] = base_addr + (addr >> 11);
1364 musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
1365
1366 /* receive data in 60-byte packets */
1367 for (i = 0; i <= (size - 1) / 60; i++) {
1368 n = size - i * 60;
1369 if (n > 60)
1370 n = 60;
1371 buffer[0] = USB_CMD_READ12;
1372 buffer[1] = n;
1373 musb_write(fUsbInterface, 2, buffer, 2, USB_TIMEOUT);
1374
1375 ret = musb_read(fUsbInterface, 1, buffer, n, USB_TIMEOUT);
1376
1377 if (ret != n) {
1378 /* try again */
1379 ret = musb_read(fUsbInterface, 1, buffer, n, USB_TIMEOUT);
1380 if (ret != n)
1381 return 0;
1382 }
1383
1384 for (j = 0; j < ret; j++)
1385 *((unsigned char *) data + j + i * 60) = buffer[j];
1386 }
1387
1388 return size;
1389 }
1390#endif // HAVE_USB
1391 } else if (fTransport == TR_USB2) {
1392#ifdef HAVE_USB
1393 unsigned char buffer[10];
1394 unsigned int base_addr;
1395 int i;
1396
1397 /* only accept even address and number of bytes */
1398 assert(addr % 2 == 0);
1399 assert(size % 2 == 0);
1400
1401 /* check for maximum size */
1402 assert(size <= USB2_BUFFER_SIZE - 10);
1403
1404 if (type == T_CTRL)
1405 base_addr = USB2_CTRL_OFFSET;
1406 else if (type == T_STATUS)
1407 base_addr = USB2_STATUS_OFFSET;
1408 else if (type == T_FIFO)
1409 base_addr = USB2_FIFO_OFFSET;
1410 else if (type == T_RAM)
1411 base_addr = USB2_RAM_OFFSET;
1412 else
1413 base_addr = 0;
1414
1415 if (type != T_RAM && size == 2) {
1416 /* word swapping: first 16 bit sit at upper address */
1417 if ((addr % 4) == 0)
1418 addr = addr + 2;
1419 else
1420 addr = addr - 2;
1421 }
1422
1423 addr += base_addr;
1424
1425 buffer[0] = USB2_CMD_READ;
1426 buffer[1] = 0;
1427
1428 buffer[2] = (addr >> 0) & 0xFF;
1429 buffer[3] = (addr >> 8) & 0xFF;
1430 buffer[4] = (addr >> 16) & 0xFF;
1431 buffer[5] = (addr >> 24) & 0xFF;
1432
1433 buffer[6] = (size >> 0) & 0xFF;
1434 buffer[7] = (size >> 8) & 0xFF;
1435 buffer[8] = (size >> 16) & 0xFF;
1436 buffer[9] = (size >> 24) & 0xFF;
1437
1438 i = musb_write(fUsbInterface, 4, buffer, 10, USB_TIMEOUT);
1439 if (i != 10)
1440 printf("musb_read error %d\n", i);
1441
1442 i = musb_read(fUsbInterface, 8, data, size, USB_TIMEOUT);
1443 return i;
1444#endif // HAVE_USB
1445 }
1446
1447 return 0;
1448}
1449
1450/*------------------------------------------------------------------*/
1451
1452void DRSBoard::SetLED(int state)
1453{
1454 // Set LED state
1455 if (state)
1456 fCtrlBits |= BIT_LED;
1457 else
1458 fCtrlBits &= ~BIT_LED;
1459 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1460}
1461
1462/*------------------------------------------------------------------*/
1463
1464void DRSBoard::SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels)
1465{
1466 // Set number of channels
1467 unsigned short d;
1468
1469 if (lastChannel < 0 || lastChannel > 10) {
1470 printf("Invalid number of channels: %d (must be between 0 and 10)\n", lastChannel);
1471 return;
1472 }
1473
1474 if (fDRSType == 2) {
1475 // register must contain last channel to read out starting from 9
1476 d = 9 - lastChannel;
1477 Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
1478 } else if (fDRSType == 3) {
1479 // upper four bits of register must contain last channel to read out starting from 9
1480 d = (firstChannel << 4) | lastChannel;
1481 Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
1482
1483 // set bit pattern for write shift register
1484 switch (nConfigChannels) {
1485 case 1:
1486 d = 0x001;
1487 break;
1488 case 2:
1489 d = 0x041;
1490 break;
1491 case 3:
1492 d = 0x111;
1493 break;
1494 case 4:
1495 d = 0x249;
1496 break;
1497 case 6:
1498 d = 0x555;
1499 break;
1500 case 12:
1501 d = 0xFFF;
1502 break;
1503 default:
1504 printf("Invalid channel configuration\n");
1505 }
1506 Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
1507 } else if (fDRSType == 4) {
1508 if (fBoardType == 6) {
1509 // determined channel readout mode A/C[even/odd], B/D[even/odd] or A/B/C/D
1510 fReadoutChannelConfig = firstChannel;
1511 Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
1512 d = (d & 0xFF00) | firstChannel; // keep higher 8 bits which are ADClkPhase
1513 Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
1514 } else {
1515 // upper four bits of register must contain last channel to read out starting from 9
1516 Read(T_CTRL, &d, REG_CHANNEL_MODE, 2);
1517 d = (d & 0xFF00) | (firstChannel << 4) | lastChannel; // keep higher 8 bits which are ADClkPhase
1518 Write(T_CTRL, REG_CHANNEL_MODE, &d, 2);
1519 }
1520
1521 // set bit pattern for write shift register
1522 fChannelConfig = 0;
1523 switch (nConfigChannels) {
1524 case 1:
1525 fChannelConfig = 0x01;
1526 break;
1527 case 2:
1528 fChannelConfig = 0x11;
1529 break;
1530 case 4:
1531 fChannelConfig = 0x55;
1532 break;
1533 case 8:
1534 fChannelConfig = 0xFF;
1535 break;
1536 default:
1537 printf("Invalid channel configuration\n");
1538 }
1539 d = fChannelConfig | (fDominoMode << 8) | (1 << 9) | (fWSRLoop << 10) | (0xF8 << 8);
1540
1541 Write(T_CTRL, REG_CHANNEL_CONFIG, &d, 2);
1542 }
1543
1544 if (fBoardType == 6) {
1545 if (fReadoutChannelConfig == 7)
1546 fNumberOfReadoutChannels = 9;
1547 else
1548 fNumberOfReadoutChannels = 5;
1549 } else {
1550 fNumberOfReadoutChannels = lastChannel - firstChannel + 1;
1551 }
1552}
1553
1554/*------------------------------------------------------------------*/
1555
1556void DRSBoard::SetNumberOfChannels(int nChannels)
1557{
1558 SetChannelConfig(0, nChannels - 1, 12);
1559}
1560
1561/*------------------------------------------------------------------*/
1562
1563void DRSBoard::SetADCClkPhase(int phase, bool invert)
1564{
1565 unsigned short d;
1566
1567 /* Set the clock phase of the ADC via the variable phase shift
1568 in the Xilinx DCM. One unit is equal to the clock period / 256,
1569 so at 30 MHz this is about 130ps. The possible range at 30 MHz
1570 is -87 ... +87 */
1571
1572 // keep lower 8 bits which are the channel mode
1573 Read(T_CTRL, &d, REG_ADCCLK_PHASE, 2);
1574 d = (d & 0x00FF) | (phase << 8);
1575 Write(T_CTRL, REG_ADCCLK_PHASE, &d, 2);
1576
1577 if (invert)
1578 fCtrlBits |= BIT_ADCCLK_INVERT;
1579 else
1580 fCtrlBits &= ~BIT_ADCCLK_INVERT;
1581 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1582
1583 fADCClkPhase = phase;
1584 fADCClkInvert = invert;
1585}
1586
1587/*------------------------------------------------------------------*/
1588
1589void DRSBoard::SetWarmup(unsigned int microseconds)
1590{
1591 /* Set the "warmup" time. When starting the domino wave, the DRS4
1592 chip together with its power supply need some time to stabilize
1593 before high resolution data can be taken (jumping baseline
1594 problem). This sets the time in ticks of 900ns before triggers
1595 are accepted */
1596
1597 unsigned short ticks;
1598
1599 if (microseconds == 0)
1600 ticks = 0;
1601 else
1602 ticks = (unsigned short) (microseconds / 0.9 + 0.5) - 1;
1603 Write(T_CTRL, REG_WARMUP, &ticks, 2);
1604}
1605
1606/*------------------------------------------------------------------*/
1607
1608void DRSBoard::SetCooldown(unsigned int microseconds)
1609{
1610 /* Set the "cooldown" time. When stopping the domino wave, the
1611 power supply needs some time to stabilize before high resolution
1612 data can read out (slanted baseline problem). This sets the
1613 time in ticks of 900 ns before the readout is started */
1614
1615 unsigned short ticks;
1616
1617 ticks = (unsigned short) (microseconds / 0.9 + 0.5) - 1;
1618 Write(T_CTRL, REG_COOLDOWN, &ticks, 2);
1619}
1620
1621/*------------------------------------------------------------------*/
1622
1623int DRSBoard::SetDAC(unsigned char channel, double value)
1624{
1625 // Set DAC value
1626 unsigned short d;
1627
1628 /* normalize to 2.5V for 16 bit */
1629 if (value < 0)
1630 value = 0;
1631 if (value > 2.5)
1632 value = 2.5;
1633 d = static_cast < unsigned short >(value / 2.5 * 0xFFFF + 0.5);
1634
1635 Write(T_CTRL, REG_DAC_OFS + (channel * 2), &d, 2);
1636
1637 return 1;
1638}
1639
1640/*------------------------------------------------------------------*/
1641
1642int DRSBoard::ReadDAC(unsigned char channel, double *value)
1643{
1644 // Readback DAC value from control register
1645 unsigned char buffer[2];
1646
1647 /* map 0->1, 1->0, 2->3, 3->2, etc. */
1648 //ofs = channel + 1 - 2*(channel % 2);
1649
1650 Read(T_CTRL, buffer, REG_DAC_OFS + (channel * 2), 2);
1651
1652 /* normalize to 2.5V for 16 bit */
1653 *value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
1654
1655 return 1;
1656}
1657
1658/*------------------------------------------------------------------*/
1659
1660int DRSBoard::GetRegulationDAC(double *value)
1661{
1662 // Get DAC value from status register (-> freq. regulation)
1663 unsigned char buffer[2];
1664
1665 if (fBoardType == 1)
1666 Read(T_STATUS, buffer, REG_RDAC3, 2);
1667 else if (fBoardType == 2 || fBoardType == 3 || fBoardType == 4)
1668 Read(T_STATUS, buffer, REG_RDAC1, 2);
1669
1670 /* normalize to 2.5V for 16 bit */
1671 *value = 2.5 * (buffer[0] + (buffer[1] << 8)) / 0xFFFF;
1672
1673 return 1;
1674}
1675
1676/*------------------------------------------------------------------*/
1677
1678int DRSBoard::StartDomino()
1679{
1680 // Start domino sampling
1681 fCtrlBits |= BIT_START_TRIG;
1682 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1683 fCtrlBits &= ~BIT_START_TRIG;
1684
1685 return 1;
1686}
1687
1688/*------------------------------------------------------------------*/
1689
1690int DRSBoard::Reinit()
1691{
1692 // Stop domino sampling
1693 // reset readout state machine
1694 // reset FIFO counters
1695 fCtrlBits |= BIT_REINIT_TRIG;
1696 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1697 fCtrlBits &= ~BIT_REINIT_TRIG;
1698
1699 return 1;
1700}
1701
1702/*------------------------------------------------------------------*/
1703
1704int DRSBoard::Init()
1705{
1706 // Init FPGA on USB2 board
1707 InitFPGA();
1708
1709 // Default values
1710
1711 // Reinitialize
1712 fCtrlBits |= BIT_REINIT_TRIG; // reset readout state machine
1713 if (fDRSType == 2)
1714 fCtrlBits &= ~BIT_FREQ_AUTO_ADJ; // turn auto. freq regul. off
1715 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1716 fCtrlBits &= ~BIT_REINIT_TRIG;
1717
1718 if (fBoardType == 1) {
1719 // set max. domino speed
1720 SetDAC(fDAC_DRA, 2.5);
1721 SetDAC(fDAC_DSA, 2.5);
1722 SetDAC(fDAC_DRB, 2.5);
1723 SetDAC(fDAC_DSB, 2.5);
1724 // set readout offset
1725 SetDAC(fDAC_COFSA, 0.9);
1726 SetDAC(fDAC_COFSB, 0.9);
1727 SetDAC(fDAC_TLEVEL, 1.7);
1728 } else if (fBoardType == 2 || fBoardType == 3) {
1729 // set max. domino speed
1730 SetDAC(fDAC_DSA, 2.5);
1731 SetDAC(fDAC_DSB, 2.5);
1732
1733 // set readout offset
1734 SetDAC(fDAC_COFS, 0.9);
1735 SetDAC(fDAC_TLEVEL, 1.7);
1736 SetDAC(fDAC_ADCOFS, 1.7); // 1.7 for DC coupling, 1.25 for AC
1737 SetDAC(fDAC_CLKOFS, 1);
1738 } else if (fBoardType == 4) {
1739 // set max. domino speed
1740 SetDAC(fDAC_DSA, 2.5);
1741 SetDAC(fDAC_DSB, 2.5);
1742
1743 // set readout offset
1744 SetDAC(fDAC_ROFS_1, 1.25); // LVDS level
1745 //SetDAC(fDAC_ROFS_2, 0.85); // linear range 0.1V ... 1.1V
1746 SetDAC(fDAC_ROFS_2, 1.05); // differential input from Lecce splitter
1747
1748 SetDAC(fDAC_ADCOFS, 1.25);
1749 SetDAC(fDAC_ACALIB, 0.5);
1750 SetDAC(fDAC_INOFS, 0.6);
1751 SetDAC(fDAC_BIAS, 0.70); // a bit above the internal bias of 0.68V
1752
1753 } else if (fBoardType == 5) {
1754 // DRS4 USB Evaluation Board 1.1 + 2.0
1755
1756 // set max. domino speed
1757 SetDAC(fDAC_DSA, 2.5);
1758
1759 // set readout offset
1760 fROFS = 1.6; // differential input range -0.5V ... +0.5V
1761 fRange = 0;
1762 SetDAC(fDAC_ROFS_1, fROFS);
1763
1764 // set common mode offset
1765 fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
1766 SetDAC(fDAC_CMOFS, fCommonMode);
1767
1768 // calibration voltage
1769 SetDAC(fDAC_CALP, fCommonMode);
1770 SetDAC(fDAC_CALN, fCommonMode);
1771
1772 // OUT- offset
1773 SetDAC(fDAC_ONOFS, 1.25);
1774
1775 SetDAC(fDAC_BIAS, 0.70);
1776
1777 } else if (fBoardType == 6) {
1778 // DRS4 Mezzanine Board 1.0
1779
1780 // set readout offset
1781 fROFS = 1.6; // differential input range -0.5V ... +0.5V
1782 fRange = 0;
1783 SetDAC(fDAC_ROFS_1, fROFS);
1784
1785 // set common mode offset
1786 fCommonMode = 0.8; // 0.8V +- 0.5V inside NMOS range
1787 SetDAC(fDAC_CMOFSP, fCommonMode);
1788 SetDAC(fDAC_CMOFSN, fCommonMode);
1789
1790 // calibration voltage
1791 SetDAC(fDAC_CALN, fCommonMode);
1792 SetDAC(fDAC_CALP, fCommonMode);
1793
1794 // OUT- offset
1795 SetDAC(fDAC_ONOFS, 1.25);
1796
1797 SetDAC(fDAC_BIAS, 0.70);
1798 }
1799
1800 /* set default number of channels per chip */
1801 if (fDRSType == 4) {
1802 if (fTransport == TR_USB2)
1803 SetChannelConfig(0, fNumberOfReadoutChannels - 1, 8);
1804 else
1805 SetChannelConfig(7, fNumberOfReadoutChannels - 1, 8);
1806 } else
1807 SetChannelConfig(0, fNumberOfReadoutChannels - 1, 12);
1808
1809 // set ADC clock phase
1810 if (fBoardType == 5) {
1811 fADCClkPhase = 0;
1812 fADCClkInvert = 0;
1813 } else if (fBoardType == 6) {
1814 fADCClkPhase = 60;
1815 fADCClkInvert = 0;
1816 }
1817
1818 // default settings
1819 fDominoMode = 1;
1820 fReadoutMode = 1;
1821 fTriggerEnable1 = 0;
1822 fTriggerEnable2 = 0;
1823 fTriggerSource = 0;
1824 fTriggerDelay = 0;
1825 fFrequency = 1;
1826 fDominoActive = 1;
1827
1828 // get some settings from hardware
1829 fRange = GetCalibratedInputRange();
1830 if (fRange < 0 || fRange > 0.5)
1831 fRange = 0;
1832 fFrequency = GetCalibratedFrequency();
1833 if (fFrequency < 0.1 || fFrequency > 6)
1834 fFrequency = 1;
1835
1836 SetDominoMode(fDominoMode);
1837 SetReadoutMode(fReadoutMode);
1838 EnableTrigger(fTriggerEnable1, fTriggerEnable2);
1839 SetTriggerSource(fTriggerSource);
1840 SetTriggerDelay(fTriggerDelay);
1841 SetDominoActive(fDominoActive);
1842 SetFrequency(fFrequency, true);
1843 SetInputRange(fRange);
1844 if (fBoardType == 5)
1845 SelectClockSource(0); // FPGA clock
1846 if (fBoardType == 6) {
1847 SetADCClkPhase(fADCClkPhase, fADCClkInvert);
1848 SetWarmup(0);
1849 SetCooldown(100);
1850 }
1851
1852 /* disable calibration signals */
1853 EnableAcal(0, 0);
1854 SetCalibTiming(0, 0);
1855
1856 return 1;
1857}
1858
1859/*------------------------------------------------------------------*/
1860
1861int DRSBoard::SetDominoMode(unsigned char mode)
1862{
1863 // Set domino mode
1864 // mode == 0: single sweep
1865 // mode == 1: run continously
1866 //
1867 fDominoMode = mode;
1868
1869 if (fDRSType == 4) {
1870 unsigned short d;
1871 Read(T_CTRL, &d, REG_CONFIG, 2);
1872 fChannelConfig = d & 0xFF;
1873
1874 d = fChannelConfig | (fDominoMode << 8) | (1 << 9) | (fWSRLoop << 10) | (0xF8 << 8);
1875 Write(T_CTRL, REG_CONFIG, &d, 2);
1876 } else {
1877 if (mode)
1878 fCtrlBits |= BIT_DMODE;
1879 else
1880 fCtrlBits &= ~BIT_DMODE;
1881
1882 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1883 }
1884
1885 return 1;
1886}
1887
1888/*------------------------------------------------------------------*/
1889
1890int DRSBoard::SetDominoActive(unsigned char mode)
1891{
1892 // Set domino activity
1893 // mode == 0: stop during readout
1894 // mode == 1: keep domino wave running
1895 //
1896 fDominoActive = mode;
1897 if (mode)
1898 fCtrlBits |= BIT_DACTIVE;
1899 else
1900 fCtrlBits &= ~BIT_DACTIVE;
1901
1902 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1903
1904 return 1;
1905}
1906
1907/*------------------------------------------------------------------*/
1908
1909int DRSBoard::SetReadoutMode(unsigned char mode)
1910{
1911 // Set readout mode
1912 // mode == 0: start from first bin
1913 // mode == 1: start from domino stop
1914 //
1915 fReadoutMode = mode;
1916 if (mode)
1917 fCtrlBits |= BIT_READOUT_MODE;
1918 else
1919 fCtrlBits &= ~BIT_READOUT_MODE;
1920
1921 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1922
1923 return 1;
1924}
1925
1926/*------------------------------------------------------------------*/
1927
1928int DRSBoard::SoftTrigger(void)
1929{
1930 // Send a software trigger
1931 fCtrlBits |= BIT_SOFT_TRIG;
1932 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1933 fCtrlBits &= ~BIT_SOFT_TRIG;
1934
1935 return 1;
1936}
1937
1938/*------------------------------------------------------------------*/
1939
1940int DRSBoard::EnableTrigger(int flag1, int flag2)
1941{
1942 // Enable external trigger
1943 fTriggerEnable1 = flag1;
1944 fTriggerEnable2 = flag2;
1945 if (flag1)
1946 fCtrlBits |= BIT_ENABLE_TRIGGER1;
1947 else
1948 fCtrlBits &= ~BIT_ENABLE_TRIGGER1;
1949
1950 if (flag2)
1951 fCtrlBits |= BIT_ENABLE_TRIGGER2;
1952 else
1953 fCtrlBits &= ~BIT_ENABLE_TRIGGER2;
1954
1955 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1956
1957 return 1;
1958}
1959
1960/*------------------------------------------------------------------*/
1961
1962int DRSBoard::SetDelayedTrigger(int flag)
1963{
1964 // Select delayed trigger from trigger bus
1965 if (flag)
1966 fCtrlBits |= BIT_TRIGGER_DELAYED;
1967 else
1968 fCtrlBits &= ~BIT_TRIGGER_DELAYED;
1969
1970 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1971
1972 return 1;
1973}
1974
1975/*------------------------------------------------------------------*/
1976
1977int DRSBoard::SetTriggerLevel(double voltage, bool negative)
1978{
1979 if (fBoardType == 5) {
1980 fTcalLevel = negative;
1981
1982 if (negative)
1983 fCtrlBits |= BIT_NEG_TRIGGER;
1984 else
1985 fCtrlBits &= ~BIT_NEG_TRIGGER;
1986
1987 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
1988
1989 return SetDAC(fDAC_TLEVEL, voltage/2 + 0.8);
1990 }
1991
1992 return 0;
1993}
1994
1995/*------------------------------------------------------------------*/
1996
1997int DRSBoard::SetTriggerDelay(int delay)
1998{
1999 short ticks;
2000 int delay0;
2001
2002 if (fBoardType == 5 || fBoardType == 6) {
2003 fTriggerDelay = delay;
2004
2005 if (fBoardType == 5) {
2006 // Adjust trigger delay to middle of window
2007 delay0 = (int) ((kNumberOfBins/fFrequency) / 2);
2008 delay0 -= 33; // internal trigger delay is about 33 ns
2009 } else
2010 delay0 = 0; // treat delay as addition to minimal delay
2011
2012 // convert delay in ns into ticks, ~4*580 ps per quad LUT
2013 ticks = (unsigned short) ((delay0 + delay) / 2.3 + 0.5);
2014 if (ticks > 255)
2015 ticks = 255;
2016 if (ticks < 0)
2017 ticks = 0;
2018 Write(T_CTRL, REG_TRG_DELAY, &ticks, 2);
2019
2020 return 1;
2021 }
2022
2023 return 0;
2024}
2025
2026/*------------------------------------------------------------------*/
2027
2028int DRSBoard::SetTriggerSource(int source)
2029{
2030 // Set trigger source
2031 // 0=CH1, 1=CH2, 2=CH3, 3=CH4
2032 if (source & 1)
2033 fCtrlBits |= BIT_TR_SOURCE1;
2034 else
2035 fCtrlBits &= ~BIT_TR_SOURCE1;
2036 if (source & 2)
2037 fCtrlBits |= BIT_TR_SOURCE2;
2038 else
2039 fCtrlBits &= ~BIT_TR_SOURCE2;
2040
2041 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2042
2043 return 1;
2044}
2045
2046/*------------------------------------------------------------------*/
2047
2048int DRSBoard::SetDelayedStart(int flag)
2049{
2050 // Enable external trigger
2051 fDelayedStart = flag;
2052 if (flag)
2053 fCtrlBits |= BIT_DELAYED_START;
2054 else
2055 fCtrlBits &= ~BIT_DELAYED_START;
2056
2057 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2058
2059 return 1;
2060}
2061
2062/*------------------------------------------------------------------*/
2063
2064int DRSBoard::SetTranspMode(int flag)
2065{
2066 // Enable/disable transparent mode
2067 fTranspMode = flag;
2068 if (flag)
2069 fCtrlBits |= BIT_TRANSP_MODE;
2070 else
2071 fCtrlBits &= ~BIT_TRANSP_MODE;
2072
2073 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2074
2075 return 1;
2076}
2077
2078/*------------------------------------------------------------------*/
2079
2080int DRSBoard::SetStandbyMode(int flag)
2081{
2082 // Enable/disable standby mode
2083 fTranspMode = flag;
2084 if (flag)
2085 fCtrlBits |= BIT_STANDBY_MODE;
2086 else
2087 fCtrlBits &= ~BIT_STANDBY_MODE;
2088
2089 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2090
2091 return 1;
2092}
2093
2094/*------------------------------------------------------------------*/
2095
2096int DRSBoard::IsBusy()
2097{
2098 // Get running flag
2099 unsigned int status;
2100
2101 Read(T_STATUS, &status, REG_STATUS, 4);
2102 return (status & BIT_RUNNING) > 0;
2103}
2104
2105/*------------------------------------------------------------------*/
2106
2107int DRSBoard::IsPLLLocked()
2108{
2109 // Get running flag
2110 unsigned int status;
2111
2112 Read(T_STATUS, &status, REG_STATUS, 4);
2113 if (GetBoardType() == 6)
2114 return ((status >> 1) & 0x0F) == 0x0F;
2115 return (status & BIT_PLL_LOCKED0) > 0;
2116}
2117
2118/*------------------------------------------------------------------*/
2119
2120int DRSBoard::IsLMKLocked()
2121{
2122 // Get running flag
2123 unsigned int status;
2124
2125 Read(T_STATUS, &status, REG_STATUS, 4);
2126 if (GetBoardType() == 6)
2127 return (status & BIT_LMK_LOCKED) > 0;
2128 return 0;
2129}
2130
2131/*------------------------------------------------------------------*/
2132
2133int DRSBoard::IsNewFreq(unsigned char chipIndex)
2134{
2135 unsigned int status;
2136
2137 Read(T_STATUS, &status, REG_STATUS, 4);
2138 if (chipIndex == 0)
2139 return (status & BIT_NEW_FREQ1) > 0;
2140 return (status & BIT_NEW_FREQ2) > 0;
2141}
2142
2143/*------------------------------------------------------------------*/
2144
2145int DRSBoard::ReadFrequency(unsigned char chipIndex, double *f)
2146{
2147 if (fDRSType == 4) {
2148
2149 if (fBoardType == 6) {
2150 *f = fFrequency;
2151 return 1;
2152 }
2153
2154 unsigned short ticks;
2155
2156 Read(T_CTRL, &ticks, REG_FREQ_SET, 2);
2157 ticks += 2;
2158
2159 /* convert rounded ticks back to frequency */
2160 if (ticks > 2)
2161 *f = 1.024 / ticks * fRefClock;
2162 else
2163 *f = 0;
2164 } else {
2165 // Read domino sampling frequency
2166 unsigned char buffer[2];
2167
2168 if (chipIndex == 0)
2169 Read(T_STATUS, buffer, REG_FREQ1, 2);
2170 else
2171 Read(T_STATUS, buffer, REG_FREQ2, 2);
2172
2173 *f = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
2174
2175 /* convert counts to frequency */
2176 if (*f != 0)
2177 *f = 1024 * 200 * (32.768E6 * 4) / (*f) / 1E9;
2178 }
2179
2180 return 1;
2181}
2182
2183/*------------------------------------------------------------------*/
2184
2185double DRSBoard::VoltToFreq(double volt)
2186{
2187 if (fDRSType == 3) {
2188 if (volt <= 1.2001)
2189 return (volt - 0.6) / 0.2;
2190 else
2191 return 0.73 / 0.28 + sqrt((0.73 / 0.28) * (0.73 / 0.28) - 2.2 / 0.14 + volt / 0.14);
2192 } else
2193 return (volt - 0.5) / 0.2;
2194}
2195
2196/*------------------------------------------------------------------*/
2197
2198double DRSBoard::FreqToVolt(double freq)
2199{
2200 if (fDRSType == 3) {
2201 if (freq <= 3)
2202 return 0.6 + 0.2 * freq;
2203 else
2204 return 2.2 - 0.73 * freq + 0.14 * freq * freq;
2205 } else
2206 return 0.55 + 0.25 * freq;
2207}
2208
2209/*------------------------------------------------------------------*/
2210
2211int DRSBoard::ConfigureLMK(double sampFreq, bool freqChange, int calFreq, int calPhase)
2212{
2213 unsigned int data[] = { 0x80000100, // RESET=1
2214 0x0007FF00, // CLKOUT0: EN=1, DIV=FF (=510) MUX=Div&Delay
2215 0x00000101, // CLKOUT1: Disabled
2216 0x0082000B, // R11: DIV4=0
2217 0x028780AD, // R13: VCO settings
2218 0x0830000E, // R14: PLL settings
2219 0xC000000F }; // R15: PLL settings
2220
2221 /* calculate dividing ratio */
2222 int divider, vco_divider, n_counter, r_counter;
2223 unsigned int status;
2224 double clk, vco;
2225
2226 if (fTransport == TR_USB2) {
2227 /* 30 MHz clock */
2228 data[4] = 0x028780AD; // R13 according to CodeLoader 4
2229 clk = 30;
2230 if (sampFreq < 1) {
2231 r_counter = 1;
2232 vco_divider = 8;
2233 n_counter = 5;
2234 } else {
2235 r_counter = 1;
2236 vco_divider = 5;
2237 n_counter = 8;
2238 }
2239 } else {
2240
2241 if (fCtrlBits & BIT_REFCLK_SOURCE) {
2242 /* 19.44 MHz clock */
2243 data[4] = 0x0284C0AD; // R13 according to CodeLoader 4
2244 clk = 19.44; // global clock through P2
2245
2246 r_counter = 2;
2247 vco_divider = 8;
2248 n_counter = 16;
2249 } else {
2250 /* 33 MHz clock */
2251 data[4] = 0x028840AD; // R13 according to CodeLoader 4
2252 clk = 33; // FPGA clock
2253
2254 r_counter = 2;
2255 vco_divider = 8;
2256 n_counter = 9;
2257 }
2258 }
2259
2260 vco = clk/r_counter*n_counter*vco_divider;
2261 divider = (int) ((vco / vco_divider / (sampFreq/2.048) / 2.0) + 0.5);
2262
2263 /* return exact frequency */
2264 fFrequency = vco/vco_divider/(divider*2)*2.048;
2265
2266 /* return exact timing calibration frequency */
2267 fTCALFrequency = vco/vco_divider;
2268
2269 /* change registers accordingly */
2270 data[1] = 0x00070000 | (divider << 8); // R0
2271 data[5] = 0x0830000E | (r_counter << 8); // R14
2272 data[6] = 0xC000000F | (n_counter << 8) | (vco_divider << 26); // R15
2273
2274 /* enable TCA output if requested */
2275 if (calFreq) {
2276 if (calFreq == 1)
2277 data[2] = 0x00050001 | ( 1<<8) ; // 148.5 MHz (33 MHz PLL)
2278 // 150 MHz (30 MHz PLL)
2279 // 155.52 MHz (19.44 MHz PLL)
2280 else if (calFreq == 2)
2281 data[2] = 0x00070001 | ( 4<<8); // above values divided by 8
2282 else if (calFreq == 3)
2283 data[2] = 0x00070001 | (255<<8); // above values divided by 510
2284 }
2285
2286 /* set delay to adjsut phase */
2287 if (calPhase > 0)
2288 data[2] |= (( calPhase & 0x0F) << 4);
2289 else if (calPhase < 0)
2290 data[1] |= ((-calPhase & 0x0F) << 4);
2291
2292 if (freqChange) {
2293 /* set all registers */
2294 for (int i=0 ; i<(int)(sizeof(data)/sizeof(unsigned int)) ; i++) {
2295 Write(T_CTRL, REG_LMK_LSB, &data[i], 2);
2296 Write(T_CTRL, REG_LMK_MSB, ((char *)&data[i])+2, 2);
2297 // poll on serial_busy flag
2298 for (int j=0 ; j<100 ; j++) {
2299 Read(T_STATUS, &status, REG_STATUS, 4);
2300 if ((status & BIT_SERIAL_BUSY) == 0)
2301 break;
2302 }
2303 }
2304 } else {
2305 /* only enable/disable timing calibration frequency */
2306 Write(T_CTRL, REG_LMK_LSB, &data[1], 2);
2307 Write(T_CTRL, REG_LMK_MSB, ((char *)&data[1])+2, 2);
2308
2309 /* poll on serial_busy flag */
2310 for (int j=0 ; j<100 ; j++) {
2311 Read(T_STATUS, &status, REG_STATUS, 4);
2312 if ((status & BIT_SERIAL_BUSY) == 0)
2313 break;
2314 }
2315
2316 Write(T_CTRL, REG_LMK_LSB, &data[2], 2);
2317 Write(T_CTRL, REG_LMK_MSB, ((char *)&data[2])+2, 2);
2318
2319 /* poll on serial_busy flag */
2320 for (int j=0 ; j<100 ; j++) {
2321 Read(T_STATUS, &status, REG_STATUS, 4);
2322 if ((status & BIT_SERIAL_BUSY) == 0)
2323 break;
2324 }
2325 }
2326
2327 return 1;
2328}
2329
2330/*------------------------------------------------------------------*/
2331
2332int DRSBoard::SetFrequency(double demand, bool wait)
2333{
2334 // Set domino sampling frequency
2335 double freq, voltage, delta_voltage;
2336 unsigned short ticks;
2337 int i, index, timeout;
2338 int dominoModeSave = fDominoMode;
2339 int triggerEnableSave1 = fTriggerEnable1;
2340 int triggerEnableSave2 = fTriggerEnable2;
2341
2342 if (fDRSType == 4) {
2343 /* allowed range is 100 MHz to 6 GHz */
2344 if (demand > 6 || demand < 0.1)
2345 return 0;
2346
2347 if (fBoardType == 6)
2348 return ConfigureLMK(demand, true, fTcalFreq, fTcalPhase);
2349
2350 /* convert frequency in GHz into ticks counted by reference clock */
2351 if (demand == 0)
2352 ticks = 0; // turn off frequency generation
2353 else
2354 ticks = static_cast < unsigned short >(1.024 / demand * fRefClock + 0.5);
2355
2356 ticks -= 2; // firmware counter need two additional clock cycles
2357 Write(T_CTRL, REG_FREQ_SET, &ticks, 2);
2358 ticks += 2;
2359
2360 /* convert rounded ticks back to frequency */
2361 if (demand > 0)
2362 demand = 1.024 / ticks * fRefClock;
2363 fFrequency = demand;
2364
2365 /* wait for PLL lock if asekd */
2366 if (wait) {
2367 StartDomino();
2368 for (i=0 ; i<1000 ; i++)
2369 if (GetStatusReg() & BIT_PLL_LOCKED0)
2370 break;
2371 if (i==100) {
2372 printf("PLL did not lock for frequency %lf\n", demand);
2373 return 0;
2374 }
2375 }
2376 } else { // fDRSType == 4
2377 SetDominoMode(1);
2378 EnableTrigger(0, 0);
2379 EnableAcal(0, 0);
2380
2381 fFrequency = demand;
2382
2383 /* turn automatic adjustment off */
2384 fCtrlBits &= ~BIT_FREQ_AUTO_ADJ;
2385
2386 /* disable external trigger */
2387 fCtrlBits &= ~BIT_ENABLE_TRIGGER1;
2388 fCtrlBits &= ~BIT_ENABLE_TRIGGER2;
2389
2390 /* set start pulse length for future DRSBoard_domino_start() */
2391 if (fDRSType == 2) {
2392 if (demand < 0.8)
2393 fCtrlBits |= BIT_LONG_START_PULSE;
2394 else
2395 fCtrlBits &= ~BIT_LONG_START_PULSE;
2396
2397 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2398 }
2399
2400 /* stop any running domino wave */
2401 Reinit();
2402
2403 /* estimate DAC setting */
2404 voltage = FreqToVolt(demand);
2405
2406 SetDAC(fDAC_DSA, voltage);
2407 SetDAC(fDAC_DSB, voltage);
2408
2409 /* wait until new DAC value has settled */
2410 Sleep(10);
2411
2412 /* restart domino wave */
2413 StartDomino();
2414
2415 ticks = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
2416
2417 /* iterate over both DRS chips */
2418 for (index = 0; index < 2; index++) {
2419
2420 /* starting voltage */
2421 voltage = FreqToVolt(demand);
2422
2423 for (i = 0; i < 100; i++) {
2424
2425 /* wait until measurement finished */
2426 for (timeout = 0; timeout < 1000; timeout++)
2427 if (IsNewFreq(index))
2428 break;
2429
2430 freq = 0;
2431 if (timeout == 1000)
2432 break;
2433
2434 ReadFrequency(index, &freq);
2435
2436 delta_voltage = FreqToVolt(demand) - FreqToVolt(freq);
2437
2438 if (fDebug) {
2439 if (fabs(freq - demand) < 0.001)
2440 printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf\n", index, i, voltage,
2441 static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq);
2442 else
2443 printf("CHIP-%d, iter%3d: %1.5lf(%05d) %7.5lf %+5d\n", index, i, voltage,
2444 static_cast < int >(voltage / 2.5 * 65535 + 0.5), freq,
2445 static_cast < int >(delta_voltage / 2.5 * 65535 + 0.5));
2446 }
2447
2448 if (fabs(freq - demand) < 0.001)
2449 break;
2450
2451 voltage += delta_voltage;
2452 if (voltage > 2.5)
2453 voltage = 2.5;
2454 if (voltage < 0)
2455 voltage = 0;
2456
2457 if (freq == 0)
2458 break;
2459
2460 if (index == 0)
2461 SetDAC(fDAC_DSA, voltage);
2462 else
2463 SetDAC(fDAC_DSB, voltage);
2464
2465 Sleep(10);
2466 }
2467 if (i == 100 || freq == 0 || timeout == 1000) {
2468 printf("Board %d --> Could not set frequency of CHIP-#%d to %1.3f GHz\n", GetBoardSerialNumber(),
2469 index, demand);
2470 return 0;
2471 }
2472 }
2473
2474 SetDominoMode(dominoModeSave);
2475 EnableTrigger(triggerEnableSave1, triggerEnableSave2);
2476 }
2477
2478 return 1;
2479}
2480
2481/*------------------------------------------------------------------*/
2482
2483int DRSBoard::RegulateFrequency(double demand)
2484{
2485 // Set frequency regulation
2486 unsigned short target, target_hi, target_lo;
2487
2488 if (demand < 0.42 || demand > 5.2)
2489 return 0;
2490
2491 fFrequency = demand;
2492
2493 /* first iterate DAC value from host */
2494 if (!SetFrequency(demand, true))
2495 return 0;
2496
2497 /* convert frequency in GHz into counts for 200 cycles */
2498 target = static_cast < unsigned short >(1024 * 200 * (32.768E6 * 4) / demand / 1E9);
2499 target_hi = target + 6;
2500 target_lo = target - 6;
2501 Write(T_CTRL, REG_FREQ_SET_HI, &target_hi, 2);
2502 Write(T_CTRL, REG_FREQ_SET_LO, &target_lo, 2);
2503
2504 /* turn on regulation */
2505 fCtrlBits |= BIT_FREQ_AUTO_ADJ;
2506 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
2507
2508 /* optional monitoring code ... */
2509#if 0
2510 do {
2511 double freq;
2512 unsigned short dac, cnt;
2513
2514 ReadFrequency(0, &freq);
2515
2516 if (fBoardType == 1)
2517 Read(T_STATUS, &dac, REG_RDAC3, 2);
2518 else if (fBoardType == 2 || fBoardType == 3)
2519 Read(T_STATUS, &dac, REG_RDAC1, 2);
2520
2521 Read(T_STATUS, &cnt, REG_FREQ1, 2);
2522
2523 if (cnt < 65535)
2524 printf("%5d %5d %5d %1.5lf\n", dac, target, cnt, freq);
2525
2526 Sleep(500);
2527 } while (1);
2528#endif
2529
2530 return 1;
2531}
2532
2533/*------------------------------------------------------------------*/
2534
2535void DRSBoard::RegisterTest()
2536{
2537 // Register test
2538#define N_REG 8
2539
2540 int i, n, n_err;
2541 unsigned int buffer[N_REG], ret[N_REG];
2542
2543 /* test single register */
2544 buffer[0] = 0x12345678;
2545 Write(T_CTRL, 0, buffer, 4);
2546 memset(ret, 0, sizeof(ret));
2547 i = Read(T_CTRL, ret, 0, 4);
2548 while (i != 4)
2549 printf("Read error single register!\n");
2550
2551 printf("Reg.0: %08X - %08X\n", buffer[0], ret[0]);
2552
2553 n_err = 0;
2554 for (n = 0; n < 100; n++) {
2555 for (i = 0; i < N_REG; i++)
2556 buffer[i] = (rand() << 16) | rand();
2557 Write(T_CTRL, 0, buffer, sizeof(buffer));
2558
2559 memset(ret, 0, sizeof(ret));
2560 i = Read(T_CTRL, ret, 0, sizeof(ret));
2561 while (i != sizeof(ret)) {
2562 printf("Read error!\n");
2563 return;
2564 }
2565
2566 for (i = 0; i < N_REG; i++) {
2567 if (n == 0)
2568 printf("Reg.%d: %08X - %08X\n", i, buffer[i], ret[i]);
2569 if (buffer[i] != ret[i]) {
2570 n_err++;
2571 }
2572 }
2573 }
2574
2575 printf("Register test: %d errors\n", n_err);
2576}
2577
2578/*------------------------------------------------------------------*/
2579
2580int DRSBoard::RAMTest(int flag)
2581{
2582#define MAX_N_BYTES 128*1024 // 128 kB
2583
2584 int i, j, n, bits, n_bytes, n_words, n_dwords;
2585 unsigned int buffer[MAX_N_BYTES/4], ret[MAX_N_BYTES/4];
2586 time_t now;
2587
2588 if (fBoardType == 6 && fTransport == TR_VME) {
2589 bits = 32;
2590 n_bytes = 128*1024; // test full 128 kB
2591 n_words = n_bytes/2;
2592 n_dwords = n_words/2;
2593 } else {
2594 bits = 24;
2595 n_words = 9*1024;
2596 n_bytes = n_words * 2;
2597 n_dwords = n_words/2;
2598 }
2599
2600 if (flag & 1) {
2601 /* integrety test */
2602 printf("Buffer size: %d (%1.1lfk)\n", n_words * 2, n_words * 2 / 1024.0);
2603 if (flag & 1) {
2604 for (i = 0; i < n_dwords; i++) {
2605 if (bits == 24)
2606 buffer[i] = (rand() | rand() << 16) & 0x00FFFFFF; // random 24-bit values
2607 else
2608 buffer[i] = (rand() | rand() << 16); // random 32-bit values
2609 }
2610
2611 Reinit();
2612 Write(T_RAM, 0, buffer, n_bytes);
2613 memset(ret, 0, n_bytes);
2614 Read(T_RAM, ret, 0, n_bytes);
2615 Reinit();
2616
2617 for (i = n = 0; i < n_dwords; i++) {
2618 if (buffer[i] != ret[i]) {
2619 n++;
2620 }
2621 if (i < 10)
2622 printf("written: %08X read: %08X\n", buffer[i], ret[i]);
2623 }
2624
2625 printf("RAM test: %d errors\n", n);
2626 }
2627 }
2628
2629 /* speed test */
2630 if (flag & 2) {
2631 /* read continously to determine speed */
2632 time(&now);
2633 while (now == time(NULL));
2634 time(&now);
2635 i = n = 0;
2636 do {
2637 memset(ret, 0, n_bytes);
2638
2639 for (j = 0; j < 10; j++) {
2640 Read(T_RAM, ret, 0, n_bytes);
2641 i += n_bytes;
2642 }
2643
2644 if (flag & 1) {
2645 for (j = 0; j < n_dwords; j++)
2646 if (buffer[j] != ret[j])
2647 n++;
2648 }
2649
2650 if (now != time(NULL)) {
2651 if (flag & 1)
2652 printf("%d read/sec, %1.2lf MB/sec, %d errors\n", static_cast < int >(i / n_bytes),
2653 i / 1024.0 / 1024.0, n);
2654 else
2655 printf("%d read/sec, %1.2lf MB/sec\n", static_cast < int >(i / n_bytes),
2656 i / 1024.0 / 1024.0);
2657 time(&now);
2658 i = 0;
2659 }
2660
2661 if (drs_kbhit())
2662 break;
2663
2664 } while (1);
2665
2666 while (drs_kbhit())
2667 getch();
2668 }
2669
2670 return 0;
2671}
2672
2673/*------------------------------------------------------------------*/
2674
2675int DRSBoard::ChipTest()
2676{
2677 int i, j, t;
2678 double freq, old_freq, min, max, mean, rms;
2679 float waveform[1024];
2680
2681 Init();
2682 SetChannelConfig(0, 8, 8);
2683 SetDominoMode(1);
2684 SetReadoutMode(1);
2685 SetDominoActive(1);
2686 SetTranspMode(0);
2687 EnableTrigger(0, 0);
2688 EnableTcal(1, 0);
2689 SelectClockSource(0);
2690 EnableAcal(1, 0);
2691
2692 /* test 1 GHz */
2693 SetFrequency(1, true);
2694 StartDomino();
2695 Sleep(100);
2696 if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
2697 puts("PLL did not lock at 1 GHz");
2698 return 0;
2699 }
2700
2701 /* test up to 6 GHz */
2702 for (freq = 5 ; freq < 6 ; freq += 0.1) {
2703 SetFrequency(freq, false);
2704 Sleep(10);
2705 if (!(GetStatusReg() & BIT_PLL_LOCKED0)) {
2706 printf("Max. frequency is %1.1lf GHz\n", old_freq);
2707 break;
2708 }
2709 ReadFrequency(0, &old_freq);
2710 }
2711
2712 /* read and check at 0 calibration voltage */
2713 SetFrequency(5, true);
2714 Sleep(10);
2715 SoftTrigger();
2716 while (IsBusy());
2717 TransferWaves(0, 8);
2718
2719 for (i=0 ; i<8 ; i++) {
2720 t = GetStopCell(0);
2721 GetWave(0, i, waveform, false, t, false);
2722 for (j=0 ; j<1024; j++)
2723 if (waveform[j] < -100 || waveform[j] > 100) {
2724 if (j<5) {
2725 /* skip this cells */
2726 } else {
2727 printf("Cell error on channel %d, cell %d: %1.1lf mV instead 0 mV\n", i, j, waveform[j]);
2728 return 0;
2729 }
2730 }
2731 }
2732
2733 /* read and check at +0.5V calibration voltage */
2734 EnableAcal(1, 0.5);
2735 StartDomino();
2736 SoftTrigger();
2737 while (IsBusy());
2738 TransferWaves(0, 8);
2739
2740 for (i=0 ; i<8 ; i++) {
2741 t = GetStopCell(0);
2742 GetWave(0, i, waveform, false, t, false);
2743 for (j=0 ; j<1024; j++)
2744 if (waveform[j] < 350) {
2745 if (j<5) {
2746 /* skip this cell */
2747 } else {
2748 printf("Cell error on channel %d, cell %d: %1.1lf mV instead 400 mV\n", i, j, waveform[j]);
2749 return 0;
2750 }
2751 }
2752 }
2753
2754 /* read and check at -0.5V calibration voltage */
2755 EnableAcal(1, -0.5);
2756 StartDomino();
2757 Sleep(10);
2758 SoftTrigger();
2759 while (IsBusy());
2760 TransferWaves(0, 8);
2761
2762 for (i=0 ; i<8 ; i++) {
2763 t = GetStopCell(0);
2764 GetWave(0, i, waveform, false, t, false);
2765 for (j=0 ; j<1024; j++)
2766 if (waveform[j] > -350) {
2767 if (j<5) {
2768 /* skip this cell */
2769 } else {
2770 printf("Cell error on channel %d, cell %d: %1.1lf mV instead -400mV\n", i, j, waveform[j]);
2771 return 0;
2772 }
2773 }
2774 }
2775
2776 /* check clock channel */
2777 GetWave(0, 8, waveform, false, 0);
2778 min = max = mean = rms = 0;
2779 for (j=0 ; j<1024 ; j++) {
2780 if (waveform[j] > max)
2781 max = waveform[j];
2782 if (waveform[j] < min)
2783 min = waveform[j];
2784 mean += waveform[j];
2785 }
2786 mean /= 1024.0;
2787 for (j=0 ; j<1024 ; j++)
2788 rms += (waveform[j] - mean) * (waveform[j] - mean);
2789 rms = sqrt(rms/1024);
2790
2791 if (max - min < 400) {
2792 printf("Error on clock channel amplitude: %1.1lf mV\n", max-min);
2793 return 0;
2794 }
2795
2796 if (rms < 100 || rms > 300) {
2797 printf("Error on clock channel RMS: %1.1lf mV\n", rms);
2798 return 0;
2799 }
2800
2801 return 1;
2802}
2803
2804/*------------------------------------------------------------------*/
2805
2806void DRSBoard::SetVoltageOffset(double offset1, double offset2)
2807{
2808 if (fDRSType == 3) {
2809 SetDAC(fDAC_ROFS_1, 0.95 - offset1);
2810 SetDAC(fDAC_ROFS_2, 0.95 - offset2);
2811 } else if (fDRSType == 2)
2812 SetDAC(fDAC_COFS, 0.9 - offset1);
2813
2814 // let DAC settle
2815 Sleep(100);
2816}
2817
2818/*------------------------------------------------------------------*/
2819
2820int DRSBoard::SetInputRange(double center)
2821{
2822 if (fBoardType == 5 || fBoardType == 6) {
2823 // DRS4 USB Evaluation Board 1.1 + Mezzanine Board
2824
2825 // only allow -0.5...0.5 to 0...1.0
2826 if (center < 0 || center > 0.5)
2827 return 0;
2828
2829 // remember range
2830 fRange = center;
2831
2832 // correct for sampling cell charge injection
2833 center *= 1.125;
2834
2835 // set readout offset
2836 fROFS = 1.6 - center;
2837 SetDAC(fDAC_ROFS_1, fROFS);
2838 }
2839
2840 return 1;
2841}
2842
2843/*------------------------------------------------------------------*/
2844
2845int DRSBoard::SetExternalClockFrequency(double frequencyMHz)
2846{
2847 // Set the frequency of the external clock
2848 fExternalClockFrequency = frequencyMHz;
2849 return 0;
2850}
2851
2852/*------------------------------------------------------------------*/
2853
2854double DRSBoard::GetExternalClockFrequency()
2855{
2856 // Return the frequency of the external clock
2857 return fExternalClockFrequency;
2858}
2859
2860/*------------------------------------------------------------------*/
2861
2862int DRSBoard::TransferWaves(int numberOfChannels)
2863{
2864 return TransferWaves(fWaveforms, numberOfChannels);
2865}
2866
2867/*------------------------------------------------------------------*/
2868
2869int DRSBoard::TransferWaves(unsigned char *p, int numberOfChannels)
2870{
2871 return TransferWaves(p, 0, numberOfChannels - 1);
2872}
2873
2874/*------------------------------------------------------------------*/
2875
2876int DRSBoard::TransferWaves(int firstChannel, int lastChannel)
2877{
2878 int offset;
2879
2880 if (fTransport == TR_USB)
2881 offset = firstChannel * sizeof(short int) * kNumberOfBins;
2882 else
2883 offset = 0; //in VME and USB2, always start from zero
2884
2885 return TransferWaves(fWaveforms + offset, firstChannel, lastChannel);
2886}
2887
2888/*------------------------------------------------------------------*/
2889
2890int DRSBoard::TransferWaves(unsigned char *p, int firstChannel, int lastChannel)
2891{
2892 // Transfer all waveforms at once from VME or USB to location
2893 int n, offset, n_requested;
2894
2895 if (lastChannel >= fNumberOfChips * fNumberOfChannels)
2896 lastChannel = fNumberOfChips * fNumberOfChannels - 1;
2897 if (lastChannel < 0) {
2898 printf("Error: Invalid channel index %d\n", lastChannel);
2899 return 0;
2900 }
2901
2902 if (firstChannel < 0 || firstChannel > fNumberOfChips * fNumberOfChannels) {
2903 printf("Error: Invalid channel index %d\n", firstChannel);
2904 return 0;
2905 }
2906
2907 if (fTransport == TR_VME) {
2908 /* in VME, always transfer all waveforms, since channels sit 'next' to each other */
2909 firstChannel = 0;
2910 lastChannel = fNumberOfChips * fNumberOfChannels - 1;
2911 if (fReadoutChannelConfig == 4)
2912 lastChannel = fNumberOfChips * 5 - 1; // special mode to read only even channels + clock
2913 }
2914
2915 else if (fTransport == TR_USB2) {
2916 /* USB2 FPGA contains 9 (Eval) or 10 (Mezz) channels */
2917 firstChannel = 0;
2918 if (fBoardType == 5)
2919 lastChannel = 8;
2920 else if (fBoardType == 6)
2921 lastChannel = 9;
2922 }
2923
2924 else if (fTransport == TR_USB) {
2925 /* USB1 FPGA contains only 16 channels */
2926 if (lastChannel > 15)
2927 lastChannel = 15;
2928 }
2929
2930 n_requested = (lastChannel - firstChannel + 1) * sizeof(short int) * kNumberOfBins;
2931 offset = firstChannel * sizeof(short int) * kNumberOfBins;
2932
2933 n = Read(T_RAM, p, offset, n_requested);
2934 if (n != n_requested) {
2935 printf("Error: only %d bytes out of %d read\n", n, n_requested);
2936 return n;
2937 }
2938
2939 // read trigger cells
2940 if (fDRSType == 4) {
2941 if (fBoardType == 5)
2942 Read(T_STATUS, fStopCell, REG_STOP_CELL0, 2);
2943 else {
2944 Read(T_STATUS, fStopCell, REG_STOP_CELL0, 2);
2945 Read(T_STATUS, fStopCell+1, REG_STOP_CELL1, 2);
2946 Read(T_STATUS, fStopCell+2, REG_STOP_CELL2, 2);
2947 Read(T_STATUS, fStopCell+3, REG_STOP_CELL3, 2);
2948 }
2949 }
2950
2951 return n;
2952}
2953
2954/*------------------------------------------------------------------*/
2955
2956int DRSBoard::DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform)
2957{
2958 return DecodeWave(fWaveforms, chipIndex, channel, waveform);
2959}
2960
2961/*------------------------------------------------------------------*/
2962
2963int DRSBoard::DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
2964 unsigned short *waveform)
2965{
2966 // Get waveform
2967 int i, offset=0, ind;
2968
2969 /* check valid parameters */
2970 assert((int)channel < fNumberOfChannels);
2971 assert((int)chipIndex < fNumberOfChips);
2972
2973 /* remap channel */
2974 if (fBoardType == 1) {
2975 if (channel < 8)
2976 channel = 7 - channel;
2977 else
2978 channel = 16 - channel;
2979 } else if (fBoardType == 6) {
2980 if (fReadoutChannelConfig == 7) {
2981 if (channel < 8)
2982 channel = 7-channel;
2983 } else if (fReadoutChannelConfig == 4) {
2984 if (channel == 8)
2985 channel = 4;
2986 else
2987 channel = 3 - channel/2;
2988 } else {
2989 channel = channel / 2;
2990 if (channel != 4)
2991 channel = 3-channel;
2992 }
2993 } else
2994 channel = channel;
2995
2996 // Read channel
2997 if (fTransport == TR_USB) {
2998 offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
2999 for (i = 0; i < kNumberOfBins; i++) {
3000 // 12-bit data
3001 waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0x0f) << 8) + waveforms[i * 2 + offset];
3002 }
3003 } else if (fTransport == TR_USB2) {
3004
3005 if (fBoardType == 5)
3006 // see dpram_map_eval1.xls
3007 offset = kNumberOfBins * 2 * (chipIndex * 16 + channel);
3008 else if (fBoardType == 6) {
3009 // see dpram_map_mezz1.xls mode 0-3
3010 offset = (kNumberOfBins * 4) * (channel % 9) + 2 * (chipIndex/2);
3011 }
3012 for (i = 0; i < kNumberOfBins; i++) {
3013 // 16-bit data
3014 if (fBoardType == 5)
3015 waveform[i] = ((waveforms[i * 2 + 1 + offset] & 0xff) << 8) + waveforms[i * 2 + offset];
3016 else if (fBoardType == 6)
3017 waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
3018 }
3019 } else if (fTransport == TR_VME) {
3020
3021 if (fBoardType == 6) {
3022 if (fReadoutChannelConfig == 7) // see dpram_map_mezz1.xls mode 7
3023 offset = (kNumberOfBins * 4) * (channel % 9 + 9*(chipIndex % 2)) + 2 * (chipIndex/2);
3024 else if (fReadoutChannelConfig == 4) // see dpram_map_mezz1.xls mode 4
3025 offset = (kNumberOfBins * 4) * (channel % 5 + 5*(chipIndex % 2)) + 2 * (chipIndex/2);
3026 for (i = 0; i < kNumberOfBins; i++)
3027 waveform[i] = ((waveforms[i * 4 + 1 + offset] & 0xff) << 8) + waveforms[i * 4 + offset];
3028 } else {
3029 offset = (kNumberOfBins * 4) * channel;
3030 for (i = 0; i < kNumberOfBins; i++) {
3031 ind = i * 4 + offset;
3032 if (chipIndex == 0)
3033 // lower 12 bit
3034 waveform[i] = ((waveforms[ind + 1] & 0x0f) << 8) | waveforms[ind];
3035 else
3036 // upper 12 bit
3037 waveform[i] = (waveforms[ind + 2] << 4) | (waveforms[ind + 1] >> 4);
3038 }
3039 }
3040 } else {
3041 printf("Error: invalid transport %d\n", fTransport);
3042 return kInvalidTransport;
3043 }
3044 return kSuccess;
3045}
3046
3047/*------------------------------------------------------------------*/
3048
3049int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform)
3050{
3051 return GetWave(chipIndex, channel, waveform, true, fStopCell[chipIndex], false, 0, true);
3052}
3053
3054/*------------------------------------------------------------------*/
3055
3056int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib,
3057 int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
3058{
3059 return GetWave(fWaveforms, chipIndex, channel, waveform, responseCalib, triggerCell, adjustToClock,
3060 threshold, offsetCalib);
3061}
3062
3063/*------------------------------------------------------------------*/
3064
3065int DRSBoard::GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib,
3066 int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
3067{
3068 int ret, i;
3069 short waveS[kNumberOfBins];
3070 ret =
3071 GetWave(fWaveforms, chipIndex, channel, waveS, responseCalib, triggerCell, adjustToClock, threshold,
3072 offsetCalib);
3073 if (responseCalib)
3074 for (i = 0; i < kNumberOfBins; i++)
3075 waveform[i] = static_cast < float >(static_cast <short> (waveS[i]) * GetPrecision());
3076 else {
3077 for (i = 0; i < kNumberOfBins; i++) {
3078 if (fBoardType == 4 || fBoardType == 5 || fBoardType == 6) {
3079 waveform[i] = static_cast < float >(waveS[i] * GetPrecision());
3080 } else
3081 waveform[i] = static_cast < float >(waveS[i]);
3082 }
3083 }
3084 return ret;
3085}
3086
3087/*------------------------------------------------------------------*/
3088
3089int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
3090 float *waveform, bool responseCalib, int triggerCell, bool adjustToClock,
3091 float threshold, bool offsetCalib)
3092{
3093 int ret, i;
3094 short waveS[kNumberOfBins];
3095 ret =
3096 GetWave(waveforms, chipIndex, channel, waveS, responseCalib, triggerCell, adjustToClock, threshold,
3097 offsetCalib);
3098
3099 if (fBoardType == 4) {
3100 for (i = 0; i < kNumberOfBins; i++)
3101 waveform[i] = static_cast < float >(waveS[i] / 65.535); // 16-bit corresponding to 1V
3102 } else {
3103 if (responseCalib) {
3104 for (i = 0; i < kNumberOfBins; i++)
3105 waveform[i] = static_cast < float >(waveS[i] * GetPrecision());
3106 } else {
3107 for (i = 0; i < kNumberOfBins; i++) {
3108 waveform[i] = static_cast < float >(waveS[i]);
3109 }
3110 }
3111 }
3112
3113 return ret;
3114}
3115
3116/*------------------------------------------------------------------*/
3117
3118int DRSBoard::GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
3119 short *waveform, bool responseCalib, int triggerCell, bool adjustToClock,
3120 float threshold, bool offsetCalib)
3121{
3122 unsigned short adcWaveform[kNumberOfBins];
3123 int ret = DecodeWave(waveforms, chipIndex, channel, adcWaveform);
3124 if (ret != kSuccess)
3125 return ret;
3126
3127 return CalibrateWaveform(chipIndex, channel, adcWaveform, waveform, responseCalib,
3128 triggerCell, adjustToClock, threshold, offsetCalib);
3129}
3130
3131/*------------------------------------------------------------------*/
3132
3133int DRSBoard::GetRawWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform,
3134 bool adjustToClock)
3135{
3136 return GetRawWave(fWaveforms, chipIndex, channel, waveform, adjustToClock);
3137}
3138
3139/*------------------------------------------------------------------*/
3140
3141int DRSBoard::GetRawWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel,
3142 unsigned short *waveform, bool adjustToClock)
3143{
3144 int i, status, tc;
3145 unsigned short wf[kNumberOfBins];
3146
3147 status = DecodeWave(waveforms, chipIndex, channel, wf);
3148
3149 if (adjustToClock) {
3150 tc = GetTriggerCell(chipIndex);
3151 for (i = 0 ; i < kNumberOfBins; i++)
3152 waveform[(i + tc) % kNumberOfBins] = wf[i];
3153 } else {
3154 for (i = 0 ; i < kNumberOfBins; i++)
3155 waveform[i] = wf[i];
3156 }
3157
3158 return status;
3159}
3160
3161/*------------------------------------------------------------------*/
3162
3163int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform,
3164 short *waveform, bool responseCalib,
3165 int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
3166{
3167 int j;
3168 double value;
3169 short left, right;
3170
3171 // calibrate waveform
3172 if (responseCalib) {
3173 if (GetDRSType() == 4) {
3174 // if Mezz though USB2 -> select correct calibration channel
3175 if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
3176 channel != 8)
3177 channel++;
3178
3179 // Channel readout mode #4 -> select correct calibration channel
3180 if (fBoardType == 6 && fReadoutChannelConfig == 4 && channel % 2 == 0 && channel != 8)
3181 channel++;
3182
3183 for (j = 0 ; j < kNumberOfBins; j++) {
3184 if (fCellCalibrationValid) {
3185 value = adcWaveform[j] - fCellOffset[channel+chipIndex*9][(j + triggerCell) % kNumberOfBins];
3186 value = value / fCellGain[channel+chipIndex*9][(j + triggerCell) % kNumberOfBins];
3187 if (offsetCalib && channel != 8)
3188 value = value - fCellOffset2[channel+chipIndex*9][j] + 32768;
3189 } else {
3190 value = adcWaveform[j];
3191 }
3192 /* convert to units of 0.1 mV */
3193 value = value / 65536.0 * 1000 * 10;
3194
3195 /* apply clipping */
3196 if (channel != 8) {
3197 if (adcWaveform[j] >= 0xFFF0 || value > (fRange * 1000 + 500) * 10)
3198 value = (fRange * 1000 + 500) * 10;
3199 if (adcWaveform[j] < 0x0010 || value < (fRange * 1000 - 500) * 10)
3200 value = (fRange * 1000 - 500) * 10;
3201 }
3202
3203 if (adjustToClock)
3204 waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
3205 else
3206 waveform[j] = (short) (value + 0.5);
3207 }
3208
3209 // check for stuck pixels and replace by average of neighbors
3210 if (fCellCalibrationValid) {
3211 for (j = 0 ; j < kNumberOfBins; j++) {
3212 if (adjustToClock) {
3213 if (fCellOffset[channel+chipIndex*9][j] == 0) {
3214 left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
3215 right = waveform[(j+1) % kNumberOfBins];
3216 waveform[j] = (short) ((left+right)/2);
3217 }
3218 } else {
3219 if (fCellOffset[channel+chipIndex*9][(j + triggerCell) % kNumberOfBins] == 0) {
3220 left = waveform[(j-1+kNumberOfBins) % kNumberOfBins];
3221 right = waveform[(j+1) % kNumberOfBins];
3222 waveform[j] = (short) ((left+right)/2);
3223 }
3224 }
3225 }
3226 }
3227
3228 } else {
3229 if (!fResponseCalibration->
3230 Calibrate(chipIndex, channel % 10, adcWaveform, waveform, triggerCell, threshold, offsetCalib))
3231 return kZeroSuppression; // return immediately if below threshold
3232 }
3233 } else {
3234 if (GetDRSType() == 4) {
3235 // if Mezz though USB2 -> select correct calibration channel
3236 if (fBoardType == 6 && (fReadoutChannelConfig == 0 || fReadoutChannelConfig == 2) &&
3237 channel != 8)
3238 channel++;
3239 for (j = 0 ; j < kNumberOfBins; j++) {
3240 value = adcWaveform[j];
3241
3242 /* convert to units of 0.1 mV */
3243 value = (value - 32768) / 65536.0 * 1000 * 10;
3244
3245 /* correct for range */
3246 value += fRange * 1000 * 10;
3247
3248 if (adjustToClock)
3249 waveform[(j + triggerCell) % kNumberOfBins] = (short) (value + 0.5);
3250 else
3251 waveform[j] = (short) (value + 0.5);
3252 }
3253 } else {
3254 for (j = 0; j < kNumberOfBins; j++) {
3255 if (adjustToClock) {
3256 // rotate waveform such that waveform[0] corresponds to bin #0 on the chip
3257 waveform[j] = adcWaveform[(kNumberOfBins-triggerCell+j) % kNumberOfBins];
3258 } else {
3259 waveform[j] = adcWaveform[j];
3260 }
3261 }
3262 }
3263 }
3264
3265 // fix bad cells for single turn mode
3266 if (GetDRSType() == 2) {
3267 if (fDominoMode == 0 && triggerCell == -1) {
3268 waveform[0] = 2 * waveform[1] - waveform[2];
3269 short m1 = (waveform[kNumberOfBins - 5] + waveform[kNumberOfBins - 6]) / 2;
3270 short m2 = (waveform[kNumberOfBins - 6] + waveform[kNumberOfBins - 7]) / 2;
3271 waveform[kNumberOfBins - 4] = m1 - 1 * (m2 - m1);
3272 waveform[kNumberOfBins - 3] = m1 - 2 * (m2 - m1);
3273 waveform[kNumberOfBins - 2] = m1 - 3 * (m2 - m1);
3274 waveform[kNumberOfBins - 1] = m1 - 4 * (m2 - m1);
3275 }
3276 }
3277
3278 return kSuccess;
3279}
3280
3281/*------------------------------------------------------------------*/
3282
3283int DRSBoard::GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period)
3284{
3285 int j;
3286 if (*time >= measurement[numberOfMeasurements - 1]) {
3287 *time -= measurement[numberOfMeasurements - 1];
3288 return 1;
3289 }
3290 if (*time < measurement[0]) {
3291 *time = *time - measurement[0] - (numberOfMeasurements - 1) * period / 2;
3292 return 1;
3293 }
3294 for (j = 0; j < numberOfMeasurements - 1; j++) {
3295 if (*time > measurement[j] && *time <= measurement[j + 1]) {
3296 *time =
3297 (period / 2) / (measurement[j + 1] - measurement[j]) * (*time - measurement[j + 1]) -
3298 (numberOfMeasurements - 2 - j) * period / 2;
3299 return 1;
3300 }
3301 }
3302 return 0;
3303}
3304
3305/*------------------------------------------------------------------*/
3306
3307int DRSBoard::GetTriggerCell(unsigned int chipIndex)
3308{
3309 if (fDRSType == 4)
3310 return GetStopCell(chipIndex);
3311
3312 return GetTriggerCell(fWaveforms, chipIndex);
3313}
3314
3315/*------------------------------------------------------------------*/
3316
3317int DRSBoard::GetTriggerCell(unsigned char *waveforms, unsigned int chipIndex)
3318{
3319 int j, triggerCell;
3320 bool calib;
3321 unsigned short baseLevel = 1000;
3322 unsigned short triggerChannel[1024];
3323
3324 if (fDRSType == 4)
3325 return GetStopCell(chipIndex);
3326
3327 GetRawWave(waveforms, chipIndex, 8, triggerChannel);
3328 calib = fResponseCalibration->SubtractADCOffset(chipIndex, 8, triggerChannel, triggerChannel, baseLevel);
3329
3330 triggerCell = -1;
3331 for (j = 0; j < kNumberOfBins; j++) {
3332 if (calib) {
3333 if (triggerChannel[j] <= baseLevel + 200
3334 && triggerChannel[(j + 1) % kNumberOfBins] > baseLevel + 200) {
3335 triggerCell = j;
3336 break;
3337 }
3338 } else {
3339 if (fDRSType == 3) {
3340 if (triggerChannel[j] <= 2000 && triggerChannel[(j + 1) % kNumberOfBins] > 2000) {
3341 triggerCell = j;
3342 break;
3343 }
3344 } else {
3345 if (triggerChannel[j] >= 2000 && triggerChannel[(j + 1) % kNumberOfBins] < 2000) {
3346 triggerCell = j;
3347 break;
3348 }
3349 }
3350 }
3351 }
3352 if (triggerCell == -1) {
3353 return kInvalidTriggerSignal;
3354 }
3355 fStopCell[0] = triggerCell;
3356 return triggerCell;
3357}
3358
3359/*------------------------------------------------------------------*/
3360
3361int DRSBoard::GetStopCell(unsigned int chipIndex)
3362{
3363 return fStopCell[chipIndex];
3364}
3365
3366/*------------------------------------------------------------------*/
3367
3368void DRSBoard::TestDAC(int channel)
3369{
3370 // Test DAC
3371 int status;
3372
3373 do {
3374 status = SetDAC(channel, 0);
3375 Sleep(1000);
3376 status = SetDAC(channel, 0.5);
3377 Sleep(1000);
3378 status = SetDAC(channel, 1);
3379 Sleep(1000);
3380 status = SetDAC(channel, 1.5);
3381 Sleep(1000);
3382 status = SetDAC(channel, 2);
3383 Sleep(1000);
3384 status = SetDAC(channel, 2.5);
3385 Sleep(1000);
3386 } while (status);
3387}
3388
3389/*------------------------------------------------------------------*/
3390
3391void DRSBoard::MeasureSpeed()
3392{
3393 // Measure domino sampling speed
3394 FILE *f;
3395 double vdr, vds, freq;
3396
3397 f = fopen("speed.txt", "wt");
3398 fprintf(f, "\t");
3399 printf("\t");
3400 for (vdr = 0.5; vdr <= 2.501; vdr += 0.05) {
3401 fprintf(f, "%1.2lf\t", vdr);
3402 printf("%1.2lf\t", vdr);
3403 }
3404 fprintf(f, "\n");
3405 printf("\n");
3406
3407 for (vds = 0.5; vds <= 2.501; vds += 0.05) {
3408 fprintf(f, "%1.2lf\t", vds);
3409 printf("%1.2lf\t", vds);
3410
3411 SetDAC(fDAC_DSA, vds);
3412 StartDomino();
3413 Sleep(1000);
3414 ReadFrequency(0, &freq);
3415
3416 fprintf(f, "%1.3lf\t", freq);
3417 printf("%1.3lf\t", freq);
3418
3419 fprintf(f, "\n");
3420 printf("\n");
3421 fflush(f);
3422 }
3423}
3424
3425/*------------------------------------------------------------------*/
3426
3427void DRSBoard::InteractSpeed()
3428{
3429 int status, i;
3430 double freq, vds;
3431
3432 do {
3433 printf("DS: ");
3434 scanf("%lf", &vds);
3435 if (vds == 0)
3436 break;
3437
3438 SetDAC(fDAC_DSA, vds);
3439 SetDAC(fDAC_DSB, vds);
3440
3441 StartDomino();
3442 for (i = 0; i < 4; i++) {
3443 Sleep(1000);
3444
3445 status = ReadFrequency(0, &freq);
3446 if (!status)
3447 break;
3448 printf("%1.6lf GHz\n", freq);
3449 }
3450
3451 /* turn BOARD_LED off */
3452 SetLED(0);
3453
3454 } while (1);
3455}
3456
3457/*------------------------------------------------------------------*/
3458
3459void DRSBoard::MonitorFrequency()
3460{
3461 // Monitor domino sampling frequency
3462 int status;
3463 unsigned int data;
3464 double freq, dac;
3465 FILE *f;
3466 time_t now;
3467 char str[256];
3468
3469 f = fopen("DRSBoard.log", "w");
3470
3471 do {
3472 Sleep(1000);
3473
3474 status = ReadFrequency(0, &freq);
3475 if (!status)
3476 break;
3477
3478 data = 0;
3479 if (fBoardType == 1)
3480 Read(T_STATUS, &data, REG_RDAC3, 2);
3481 else if (fBoardType == 2 || fBoardType == 3)
3482 Read(T_STATUS, &data, REG_RDAC1, 2);
3483
3484 dac = data / 65536.0 * 2.5;
3485 printf("%1.6lf GHz, %1.4lf V\n", freq, dac);
3486 time(&now);
3487 strcpy(str, ctime(&now) + 11);
3488 str[8] = 0;
3489
3490 fprintf(f, "%s %1.6lf GHz, %1.4lf V\n", str, freq, dac);
3491 fflush(f);
3492
3493 } while (!drs_kbhit());
3494
3495 fclose(f);
3496}
3497
3498/*------------------------------------------------------------------*/
3499
3500int DRSBoard::TestShift(int n)
3501{
3502 // Test shift register
3503 unsigned char buffer[3];
3504
3505 memset(buffer, 0, sizeof(buffer));
3506
3507#if 0
3508 buffer[0] = CMD_TESTSHIFT;
3509 buffer[1] = n;
3510
3511 status = msend_usb(buffer, 2);
3512 if (status != 2)
3513 return status;
3514
3515 status = mrecv_usb(buffer, sizeof(buffer));
3516 if (status != 1)
3517 return status;
3518#endif
3519
3520 if (buffer[0] == 1)
3521 printf("Shift register %c works correctly\n", 'A' + n);
3522 else if (buffer[0] == 2)
3523 printf("SROUT%c does hot go high after reset\n", 'A' + n);
3524 else if (buffer[0] == 3)
3525 printf("SROUT%c does hot go low after 1024 clocks\n", 'A' + n);
3526
3527 return 1;
3528}
3529
3530/*------------------------------------------------------------------*/
3531
3532unsigned int DRSBoard::GetCtrlReg()
3533{
3534 unsigned int status;
3535
3536 Read(T_CTRL, &status, REG_CTRL, 4);
3537 return status;
3538}
3539
3540/*------------------------------------------------------------------*/
3541
3542unsigned short DRSBoard::GetConfigReg()
3543{
3544 unsigned short status;
3545
3546 Read(T_CTRL, &status, REG_CONFIG, 2);
3547 return status;
3548}
3549
3550/*------------------------------------------------------------------*/
3551
3552unsigned int DRSBoard::GetStatusReg()
3553{
3554 unsigned int status;
3555
3556 Read(T_STATUS, &status, REG_STATUS, 4);
3557 return status;
3558}
3559
3560/*------------------------------------------------------------------*/
3561
3562int DRSBoard::EnableTcal(int freq, int level, int phase)
3563{
3564 fTcalFreq = freq;
3565 fTcalLevel = level;
3566 fTcalPhase = phase;
3567
3568 if (fBoardType == 6) {
3569 ConfigureLMK(fFrequency, false, freq, phase);
3570 } else {
3571 // Enable clock channel
3572 if (freq)
3573 fCtrlBits |= BIT_TCAL_EN;
3574 else
3575 fCtrlBits &= ~BIT_TCAL_EN;
3576
3577 // Set output level, needed for gain calibration
3578 if (fDRSType == 4) {
3579 if (level)
3580 fCtrlBits |= BIT_NEG_TRIGGER;
3581 else
3582 fCtrlBits &= ~BIT_NEG_TRIGGER;
3583 }
3584
3585 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3586 }
3587
3588 return 1;
3589}
3590
3591/*------------------------------------------------------------------*/
3592
3593int DRSBoard::SelectClockSource(int source)
3594{
3595 fTcalSource = source;
3596
3597 // Select clock source:
3598 // EVAL1: synchronous (0) or asynchronous (1) (2nd quartz)
3599 if (source)
3600 fCtrlBits |= BIT_TCAL_SOURCE;
3601 else
3602 fCtrlBits &= ~BIT_TCAL_SOURCE;
3603
3604 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3605
3606 return 1;
3607}
3608
3609/*------------------------------------------------------------------*/
3610
3611int DRSBoard::SetRefclk(int source)
3612{
3613 // Select reference clock source to internal FPGA (0) or external P2 (1)
3614 if (source)
3615 fCtrlBits |= BIT_REFCLK_SOURCE;
3616 else
3617 fCtrlBits &= ~BIT_REFCLK_SOURCE;
3618
3619 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3620
3621 return 1;
3622}
3623
3624/*------------------------------------------------------------------*/
3625
3626int DRSBoard::EnableAcal(int mode, double voltage)
3627{
3628 double t1, t2;
3629
3630 fAcalMode = mode;
3631 fAcalVolt = voltage;
3632
3633 if (mode == 0) {
3634 /* turn calibration off */
3635 SetCalibTiming(0, 0);
3636 if (fBoardType == 5 || fBoardType == 6) {
3637 /* turn voltages off (50 Ohm analog switch!) */
3638 SetDAC(fDAC_CALP, 0);
3639 SetDAC(fDAC_CALN, 0);
3640 }
3641 fCtrlBits &= ~BIT_ACAL_EN;
3642 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3643 } else if (mode == 1) {
3644 /* static calibration */
3645 SetCalibVoltage(voltage);
3646 SetCalibTiming(0, 0);
3647 fCtrlBits |= BIT_ACAL_EN;
3648 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3649 } else if (mode == 2) {
3650 /* first part calibration:
3651 stop domino wave after 1.2 revolutions
3652 turn on calibration voltage after 0.1 revolutions */
3653
3654 /* ensure circulating domino wave */
3655 SetDominoMode(1);
3656
3657 /* set calibration voltage but do not turn it on now */
3658 SetCalibVoltage(voltage);
3659 fCtrlBits &= ~BIT_ACAL_EN;
3660 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3661
3662 /* calculate duration of DENABLE signal as 1.2 revolutions */
3663 t1 = 1 / fFrequency * 1024 * 1.2; // ns
3664 t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
3665 t2 = 1 / fFrequency * 1024 * 0.1; // ns
3666 t2 = static_cast < int >((t2 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
3667 SetCalibTiming(static_cast < int >(t1), static_cast < int >(t2));
3668
3669 } else if (mode == 3) {
3670 /* second part calibration:
3671 stop domino wave after 1.05 revolutions */
3672
3673 /* ensure circulating domino wave */
3674 SetDominoMode(1);
3675
3676 /* turn on and let settle calibration voltage */
3677 SetCalibVoltage(voltage);
3678 fCtrlBits |= BIT_ACAL_EN;
3679 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3680
3681 /* calculate duration of DENABLE signal as 1.1 revolutions */
3682 t1 = 1 / fFrequency * 1024 * 1.05; // ns
3683 t1 = static_cast < int >((t1 - 30) / 30 + 1); // 30 ns offset, 30 ns units, rounded up
3684 SetCalibTiming(static_cast < int >(t1), 0);
3685 }
3686
3687 return 1;
3688}
3689
3690/*------------------------------------------------------------------*/
3691
3692int DRSBoard::SetCalibTiming(int t_enable, int t_cal)
3693{
3694 unsigned short d;
3695
3696 if (fDRSType == 2) {
3697 d = t_cal | (t_enable << 8);
3698 Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
3699 }
3700
3701 if (fDRSType == 3) {
3702 d = t_cal;
3703 Write(T_CTRL, REG_CALIB_TIMING, &d, 2);
3704 }
3705
3706 return 1;
3707}
3708
3709/*------------------------------------------------------------------*/
3710
3711int DRSBoard::SetCalibVoltage(double value)
3712{
3713 // Set Calibration Voltage
3714 if (fBoardType == 5 || fBoardType == 6) {
3715 if (fBoardType == 5)
3716 value = value * (1+fFrequency/65); // rough correction factor for input current
3717 SetDAC(fDAC_CALP, fCommonMode + value / 2);
3718 SetDAC(fDAC_CALN, fCommonMode - value / 2);
3719 } else
3720 SetDAC(fDAC_ACALIB, value);
3721 return 1;
3722}
3723
3724/*------------------------------------------------------------------*/
3725
3726int DRSBoard::StartClearCycle()
3727{
3728 /* clear cycle is necessary for DRS4 to reduce noise */
3729
3730 fbkAcalVolt = fAcalVolt;
3731 fbkAcalMode = fAcalMode;
3732 fbkTcalFreq = fTcalFreq;
3733 fbkTcalLevel = fTcalLevel;
3734
3735 /* switch all inputs to zero */
3736 EnableAcal(1, 0);
3737
3738 /* start, stop and readout of zero */
3739 StartDomino();
3740 SoftTrigger();
3741
3742 return 1;
3743}
3744
3745/*------------------------------------------------------------------*/
3746
3747int DRSBoard::FinishClearCycle()
3748{
3749 while (IsBusy());
3750
3751 /* restore old values */
3752 EnableAcal(fbkAcalMode, fbkAcalVolt);
3753
3754 return 1;
3755}
3756
3757/*------------------------------------------------------------------*/
3758
3759double DRSBoard::GetTemperature()
3760{
3761 // Read Out Temperature Sensor
3762 unsigned char buffer[2];
3763 unsigned short d;
3764 double temperature;
3765
3766 Read(T_STATUS, buffer, REG_TEMPERATURE, 2);
3767
3768 d = (static_cast < unsigned int >(buffer[1]) << 8) +buffer[0];
3769 temperature = ((d >> 3) & 0x0FFF) * 0.0625;
3770
3771 return temperature;
3772}
3773
3774/*------------------------------------------------------------------*/
3775
3776int DRSBoard::GetTriggerBus()
3777{
3778 unsigned short status;
3779
3780 Read(T_STATUS, &status, REG_TRIGGER_BUS, 2);
3781 return static_cast < int >(status);
3782}
3783
3784/*------------------------------------------------------------------*/
3785
3786int DRSBoard::SetBoardSerialNumber(unsigned short serialNumber)
3787{
3788 unsigned char buf[32768];
3789
3790 unsigned short dac;
3791
3792 if (fDRSType < 4) {
3793 // read current DAC register
3794 Read(T_CTRL, &dac, REG_DAC0, 2);
3795
3796 // put serial in DAC register
3797 Write(T_CTRL, REG_DAC0, &serialNumber, 2);
3798
3799 // execute flash
3800 fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
3801 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3802 fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
3803
3804 // wait 6ms per word
3805 Sleep(20);
3806
3807 // write back old DAC registers
3808 Write(T_CTRL, REG_DAC0, &dac, 2);
3809
3810 // read back serial number
3811 ReadSerialNumber();
3812
3813 } else if (fDRSType == 4) {
3814 /* merge serial number into eeprom page #0 */
3815 ReadEEPROM(0, buf, sizeof(buf));
3816 buf[0] = serialNumber & 0xFF;
3817 buf[1] = serialNumber >> 8;
3818 WriteEEPROM(0, buf, sizeof(buf));
3819
3820 /* erase DPRAM */
3821 memset(buf, 0, sizeof(buf));
3822 Write(T_RAM, 0, buf, sizeof(buf));
3823
3824 /* read back EEPROM */
3825 ReadEEPROM(0, buf, sizeof(buf));
3826
3827 /* check if correctly set */
3828 if (((buf[1] << 8) | buf[0]) != serialNumber)
3829 return 0;
3830
3831 fBoardSerialNumber = serialNumber;
3832 }
3833
3834 return 1;
3835}
3836
3837/*------------------------------------------------------------------*/
3838
3839int DRSBoard::ReadEEPROM(unsigned short page, void *buffer, int size)
3840{
3841 int i;
3842 unsigned long status;
3843 // write eeprom page number
3844 if (fBoardType == 5)
3845 Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
3846 else if (fBoardType == 6)
3847 Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
3848 else return -1;
3849
3850 // execute eeprom read
3851 fCtrlBits |= BIT_EEPROM_READ_TRIG;
3852 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3853 fCtrlBits &= ~BIT_EEPROM_READ_TRIG;
3854
3855 // poll on serial_busy flag
3856 for (i=0 ; i<100 ; i++) {
3857 Read(T_STATUS, &status, REG_STATUS, 4);
3858 if ((status & BIT_SERIAL_BUSY) == 0) break;
3859 Sleep(10);
3860 }
3861
3862 return Read(T_RAM, buffer, 0, size);
3863}
3864
3865/*------------------------------------------------------------------*/
3866
3867int DRSBoard::WriteEEPROM(unsigned short page, void *buffer, int size)
3868{
3869 int i;
3870 unsigned long status;
3871
3872 // write eeprom page number
3873 if (fBoardType == 5)
3874 Write(T_CTRL, REG_EEPROM_PAGE_EVAL, &page, 2);
3875 else if (fBoardType == 6)
3876 Write(T_CTRL, REG_EEPROM_PAGE_MEZZ, &page, 2);
3877 else
3878 return -1;
3879
3880 // write eeprom page to RAM
3881 Write(T_RAM, 0, buffer, size);
3882
3883 // execute eeprom write
3884 fCtrlBits |= BIT_EEPROM_WRITE_TRIG;
3885 Write(T_CTRL, REG_CTRL, &fCtrlBits, 4);
3886 fCtrlBits &= ~BIT_EEPROM_WRITE_TRIG;
3887
3888 // poll on serail_busy flag
3889 for (i=0 ; i<500 ; i++) {
3890 Read(T_STATUS, &status, REG_STATUS, 4);
3891 if ((status & BIT_SERIAL_BUSY) == 0)
3892 break;
3893 Sleep(10);
3894 }
3895
3896 return 1;
3897}
3898
3899/*------------------------------------------------------------------*/
3900
3901int DRSBoard::GetTime(unsigned int chipIndex, float *time, bool tcalibrated, bool rotated)
3902{
3903 int i;
3904
3905 /* for DRS2, please use function below */
3906 if (fDRSType < 4)
3907 return GetTime(chipIndex, fFrequency, time, tcalibrated, rotated);
3908
3909 if (!fTimingCalibrationValid || !tcalibrated || fabs(fTimingCalibratedFrequency - fFrequency)>0.01) {
3910 double t0 = fStopCell[chipIndex] / fFrequency;
3911 for (i = 0; i < kNumberOfBins; i++) {
3912 if (rotated)
3913 time[i] = static_cast < float >(((i+fStopCell[chipIndex]) % kNumberOfBins) / fFrequency - t0);
3914 else
3915 time[i] = static_cast < float >(i / fFrequency);
3916 if (time[i] < 0)
3917 time[i] += static_cast < float > (kNumberOfBins / fFrequency);
3918 }
3919 return 1;
3920 }
3921
3922 double t0 = fCellT[chipIndex][fStopCell[chipIndex]];
3923
3924 for (i=0 ; i<kNumberOfBins ; i++) {
3925 if (rotated)
3926 time[i] = static_cast < float > (fCellT[chipIndex][(i+fStopCell[chipIndex]) % kNumberOfBins] - t0);
3927 else
3928 time[i] = static_cast < float > (fCellT[chipIndex][i]);
3929 if (time[i] < 0)
3930 time[i] += static_cast < float > (kNumberOfBins / fFrequency);
3931 }
3932 return 1;
3933}
3934
3935/*------------------------------------------------------------------*/
3936
3937int DRSBoard::GetTime(unsigned int chipIndex, double freqGHz, float *time, bool tcalibrated, bool rotated)
3938{
3939 /* for DRS4, use function above */
3940 if (fDRSType == 4)
3941 return GetTime(chipIndex, time, tcalibrated, rotated);
3942
3943 int i, irot;
3944 DRSBoard::TimeData * init;
3945 DRSBoard::TimeData::FrequencyData * freq;
3946 int frequencyMHz = (int)(freqGHz*1000);
3947
3948 init = GetTimeCalibration(chipIndex);
3949
3950 if (init == NULL) {
3951 for (i = 0; i < kNumberOfBins; i++)
3952 time[i] = static_cast < float >(i / fFrequency);
3953 return 1;
3954 }
3955 freq = NULL;
3956 for (i = 0; i < init->fNumberOfFrequencies; i++) {
3957 if (init->fFrequency[i]->fFrequency == frequencyMHz) {
3958 freq = init->fFrequency[i];
3959 break;
3960 }
3961 }
3962 if (freq == NULL) {
3963 for (i = 0; i < kNumberOfBins; i++)
3964 time[i] = static_cast < float >(i / fFrequency);
3965 return 1;
3966 }
3967 for (i = 0; i < kNumberOfBins; i++) {
3968 irot = (fStopCell[chipIndex] + i) % kNumberOfBins;
3969 if (fStopCell[chipIndex] + i < kNumberOfBins)
3970 time[i] = static_cast < float >((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]]) / fFrequency);
3971 else
3972 time[i] =
3973 static_cast <
3974 float
3975 >((freq->fBin[irot] - freq->fBin[fStopCell[chipIndex]] + freq->fBin[kNumberOfBins - 1] - 2 * freq->fBin[0] +
3976 freq->fBin[1]) / fFrequency);
3977 }
3978 return 1;
3979}
3980
3981/*------------------------------------------------------------------*/
3982
3983bool DRSBoard::InitTimeCalibration(unsigned int chipIndex)
3984{
3985 return GetTimeCalibration(chipIndex, true) != NULL;
3986}
3987
3988/*------------------------------------------------------------------*/
3989
3990DRSBoard::TimeData * DRSBoard::GetTimeCalibration(unsigned int chipIndex, bool reinit)
3991{
3992 int i, l, index;
3993 char *cstop;
3994 char fileName[500];
3995 char error[240];
3996 PMXML_NODE node, rootNode, mainNode;
3997
3998 index = fNumberOfTimeData;
3999 for (i = 0; i < fNumberOfTimeData; i++) {
4000 if (fTimeData[i]->fChip == static_cast < int >(chipIndex)) {
4001 if (!reinit)
4002 return fTimeData[i];
4003 else {
4004 index = i;
4005 break;
4006 }
4007 }
4008 }
4009
4010 fTimeData[index] = new DRSBoard::TimeData();
4011 DRSBoard::TimeData * init = fTimeData[index];
4012
4013 init->fChip = chipIndex;
4014
4015 for (i = 0; i < init->kMaxNumberOfFrequencies; i++) {
4016 if (i <= 499 || (i >= 501 && i <= 999) || (i >= 1001 && i <= 1499) || (i >= 1501 && i <= 1999) ||
4017 (i >= 2001 && i <= 2499) || i >= 2501)
4018 continue;
4019 sprintf(fileName, "%s/board%d/TimeCalib_board%d_chip%d_%dMHz.xml", fCalibDirectory, fBoardSerialNumber,
4020 fBoardSerialNumber, chipIndex, i);
4021 rootNode = mxml_parse_file(fileName, error, sizeof(error));
4022 if (rootNode == NULL)
4023 continue;
4024
4025 init->fFrequency[init->fNumberOfFrequencies] = new DRSBoard::TimeData::FrequencyData();
4026 init->fFrequency[init->fNumberOfFrequencies]->fFrequency = i;
4027
4028 mainNode = mxml_find_node(rootNode, "/DRSTimeCalibration");
4029
4030 for (l = 0; l < kNumberOfBins; l++) {
4031 node = mxml_subnode(mainNode, l + 2);
4032 init->fFrequency[init->fNumberOfFrequencies]->fBin[l] = strtod(mxml_get_value(node), &cstop);
4033 }
4034 mxml_free_tree(rootNode);
4035 init->fNumberOfFrequencies++;
4036 }
4037 if (init->fNumberOfFrequencies == 0) {
4038 printf("Board %d --> Could not find time calibration file\n", GetBoardSerialNumber());
4039 }
4040
4041 if (index == fNumberOfTimeData)
4042 fNumberOfTimeData++;
4043
4044 return fTimeData[index];
4045}
4046
4047/*------------------------------------------------------------------*/
4048
4049void DRSBoard::SetCalibrationDirectory(const char *calibrationDirectoryPath)
4050{
4051 strncpy(fCalibDirectory, calibrationDirectoryPath, strlen(calibrationDirectoryPath));
4052 fCalibDirectory[strlen(calibrationDirectoryPath)] = 0;
4053};
4054
4055/*------------------------------------------------------------------*/
4056
4057void DRSBoard::GetCalibrationDirectory(char *calibrationDirectoryPath)
4058{
4059 strncpy(calibrationDirectoryPath, fCalibDirectory, strlen(fCalibDirectory));
4060 calibrationDirectoryPath[strlen(fCalibDirectory)] = 0;
4061};
4062
4063/*------------------------------------------------------------------*/
4064
4065void DRSBoard::LinearRegression(double *x, double *y, int n, double *a, double *b)
4066{
4067 int i;
4068 double sx, sxx, sy, sxy;
4069
4070 sx = sxx = sy = sxy = 0;
4071 for (i = 0; i < n; i++) {
4072 sx += x[i];
4073 sxx += x[i] * x[i];
4074 sy += y[i];
4075 sxy += x[i] * y[i];
4076 }
4077
4078 *a = (n * sxy - sx * sy) / (n * sxx - sx * sx);
4079 *b = (sy - *a * sx) / n;
4080}
4081
4082/*------------------------------------------------------------------*/
4083
4084void DRSBoard::ReadSingleWaveform(int nChip, int nChan,
4085 unsigned short wf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins],
4086 bool rotated)
4087{
4088 int i, j, k, tc;
4089
4090 StartDomino();
4091 SoftTrigger();
4092 while (IsBusy());
4093 TransferWaves();
4094
4095 for (i=0 ; i<nChip ; i++) {
4096 tc = GetTriggerCell(i);
4097
4098 for (j=0 ; j<nChan ; j++) {
4099 GetRawWave(i, j, wf[i][j], rotated);
4100 if (!rotated) {
4101 for (k=0 ; k<kNumberOfBins ; k++) {
4102 /* do primary offset calibration */
4103 wf[i][j][k] = wf[i][j][k] - fCellOffset[j+i*9][(k + tc) % kNumberOfBins] + 32768;
4104 }
4105 }
4106 }
4107 }
4108}
4109
4110#define WFH_SIZE 100
4111
4112static unsigned short wfh[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins][WFH_SIZE];
4113static float weight[] = {
4114 0.1f,
4115 0.2f,
4116 0.4f,
4117 0.6f,
4118 0.8f,
4119 1.0f,
4120 1.0f,
4121 1.0f,
4122 0.8f,
4123 0.6f,
4124 0.4f,
4125 0.2f,
4126 0.1f,
4127};
4128static unsigned short swf[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
4129static unsigned short htmp[WFH_SIZE];
4130static float center[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
4131static int icenter[kNumberOfChipsMax][kNumberOfChannelsMax][kNumberOfBins];
4132
4133int DRSBoard::AverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
4134 int prog1, int prog2, unsigned short *awf, int n, bool rotated)
4135{
4136 int i, j, k, l, prog, old_prog = 0;
4137 float cm;
4138
4139 if (pcb != NULL)
4140 pcb->Progress(prog1);
4141
4142 memset(center, 0, sizeof(center));
4143
4144 for (i=0 ; i<n; i++) {
4145 ReadSingleWaveform(nChip, nChan, swf, rotated);
4146
4147 for (j=0 ; j<nChip ; j++) {
4148 for (k=0 ; k<nChan ; k++) {
4149 if (i > 5) {
4150 /* calculate and subtract common mode */
4151 for (l=0,cm=0 ; l<kNumberOfBins ; l++)
4152 cm += swf[j][k][l] - 32768;
4153 cm /= kNumberOfBins;
4154 for (l=0 ; l<kNumberOfBins ; l++)
4155 center[j][k][l] += swf[j][k][l]- cm;
4156 }
4157 }
4158 }
4159
4160 prog = (int)(((double)i/n)*(prog2-prog1)+prog1);
4161 if (prog > old_prog) {
4162 old_prog = prog;
4163 if (pcb != NULL)
4164 pcb->Progress(prog);
4165 }
4166 }
4167
4168 for (i=0 ; i<nChip ; i++)
4169 for (j=0 ; j<nChan ; j++)
4170 for (k=0 ; k<kNumberOfBins ; k++)
4171 awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short)(center[i][j][k]/(n-6) + 0.5);
4172
4173 return 1;
4174}
4175
4176int DRSBoard::RobustAverageWaveforms(DRSCallback *pcb, int nChip, int nChan,
4177 int prog1, int prog2, unsigned short *awf, int n, bool rotated)
4178{
4179 int i, j, k, l, prog, old_prog = 0;
4180 int nw, bin, max, imax;
4181 float mean, norm;
4182
4183 if (pcb != NULL)
4184 pcb->Progress(prog1);
4185
4186 memset(wfh, 0, sizeof(wfh));
4187 memset(center, 0, sizeof(center));
4188
4189 /* obtain center of histograms */
4190 for (i=0 ; i<10 ; i++) {
4191 ReadSingleWaveform(nChip, nChan, swf, rotated);
4192 for (j=0 ; j<nChip ; j++)
4193 for (k=0 ; k<nChan ; k++)
4194 for (l=0 ; l<kNumberOfBins ; l++) {
4195 center[j][k][l] += swf[j][k][l]/10.0f;
4196 }
4197
4198 /* update progress bar */
4199 prog = (int)(((double)i/(n+10))*(prog2-prog1)+prog1);
4200 if (prog > old_prog) {
4201 old_prog = prog;
4202 if (pcb != NULL)
4203 pcb->Progress(prog);
4204 }
4205 }
4206 for (j=0 ; j<nChip ; j++)
4207 for (k=0 ; k<nChan ; k++)
4208 for (l=0 ; l<kNumberOfBins ; l++)
4209 icenter[j][k][l] = (int)(center[j][k][l]/16+0.5)*16;
4210
4211 /* fill histograms */
4212 for (i=0 ; i<n ; i++) {
4213 ReadSingleWaveform(nChip, nChan, swf, rotated);
4214 for (j=0 ; j<nChip ; j++)
4215 for (k=0 ; k<nChan ; k++)
4216 for (l=0 ; l<kNumberOfBins ; l++) {
4217 bin = (swf[j][k][l]-icenter[j][k][l])/16+WFH_SIZE/2;
4218 if (bin < 0)
4219 bin = 0;
4220 if (bin > WFH_SIZE-1)
4221 bin = WFH_SIZE-1;
4222 wfh[j][k][l][bin]++;
4223 }
4224
4225 /* update progress bar */
4226 prog = (int)(((double)(i+10)/(n+10))*(prog2-prog1)+prog1);
4227 if (prog > old_prog) {
4228 old_prog = prog;
4229 if (pcb != NULL)
4230 pcb->Progress(prog);
4231 }
4232 }
4233
4234 /*
4235 FILE *fh = fopen("calib.csv", "wt");
4236 for (i=40 ; i<60 ; i++) {
4237 for (j=0 ; j<WFH_SIZE ; j++)
4238 fprintf(fh, "%d;", wfh[0][0][i][j]);
4239 fprintf(fh, "\n");
4240 }
4241 fclose(fh);
4242 */
4243
4244 /* shift histograms to center */
4245 for (i=0 ; i<nChip ; i++) {
4246 for (j=0 ; j<nChan ; j++) {
4247 for (k=0 ; k<kNumberOfBins ; k++) {
4248 max = imax = 0;
4249 for (l=0 ; l<WFH_SIZE ; l++) {
4250 if (wfh[i][j][k][l] > max) {
4251 max = wfh[i][j][k][l];
4252 imax = l;
4253 }
4254 }
4255 for (l=0 ; l<WFH_SIZE ; l++) {
4256 bin = l+imax-WFH_SIZE/2;
4257 if (bin < 0 || bin > WFH_SIZE-1)
4258 htmp[l] = 0;
4259 else
4260 htmp[l] = wfh[i][j][k][bin];
4261 }
4262 for (l=0 ; l<WFH_SIZE ; l++)
4263 wfh[i][j][k][l] = htmp[l];
4264 icenter[i][j][k] += (imax-WFH_SIZE/2)*16;
4265 }
4266 }
4267 }
4268
4269 /* do a weighted average */
4270 nw = sizeof(weight)/sizeof(float);
4271 for (i=0 ; i<nChip ; i++) {
4272 for (j=0 ; j<nChan ; j++) {
4273 for (k=0 ; k<kNumberOfBins ; k++) {
4274 mean = norm = 0;
4275 for (l=0 ; l<nw ; l++) {
4276 mean += wfh[i][j][k][WFH_SIZE/2 + l-nw/2] * weight[l] * (icenter[i][j][k] + (l-nw/2)*16);
4277 norm += wfh[i][j][k][WFH_SIZE/2 + l-nw/2] * weight[l];
4278 }
4279 if (norm == 0)
4280 awf[(i*nChan+j)*kNumberOfBins+k] = 0;
4281 else
4282 awf[(i*nChan+j)*kNumberOfBins+k] = (unsigned short) (mean/norm+0.5);
4283 }
4284 }
4285 }
4286
4287 /*
4288 FILE *fh = fopen("calib.csv", "wt");
4289 for (i=40 ; i<60 ; i++) {
4290 fprintf(fh, "%d;", icenter[0][0][0] + (i - WFH_SIZE/2)*16);
4291 fprintf(fh, "%d;", wfh[0][0][0][i]);
4292 if (i == 50)
4293 fprintf(fh, "%d;", awf[0]);
4294 fprintf(fh, "\n");
4295 }
4296 fclose(fh);
4297 */
4298
4299 if (pcb != NULL)
4300 pcb->Progress(prog2);
4301
4302 return 1;
4303}
4304
4305/*------------------------------------------------------------------*/
4306
4307int idx[4][10] = {
4308 { 0, 2, 4, 6, 8, 18, 20, 22, 24, 26 },
4309 { 1, 3, 5, 7, 39, 19, 21, 23, 25, 39 },
4310 { 9, 11, 13, 15, 17, 27, 29, 31, 33, 35 },
4311 { 10, 12, 14, 16, 39, 28, 30, 32, 34, 39 },
4312};
4313
4314#define F1(x) ((int) (84.0/24 * (x)))
4315#define F2(x) ((int) (92.0/8 * (x)))
4316
4317static unsigned short wft[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
4318 wf1[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
4319 wf2[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024],
4320 wf3[kNumberOfChipsMax*kNumberOfChannelsMax*kNumberOfChipsMax][1024];
4321
4322int DRSBoard::CalibrateVolt(DRSCallback *pcb)
4323{
4324int i, j, nChan, timingChan=0, chip, config, p, clkon, refclk, trg1, trg2, n_stuck;
4325double f, r;
4326unsigned short buf[kNumberOfBins*kNumberOfCalibChannelsV4*2];
4327
4328 f = fFrequency;
4329 r = fRange;
4330 clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
4331 refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
4332 trg1 = fTriggerEnable1;
4333 trg2 = fTriggerEnable2;
4334
4335 Init();
4336 fFrequency = f;
4337 SetRefclk(refclk);
4338 SetFrequency(fFrequency, true);
4339 SetDominoMode(1);
4340 SetDominoActive(1);
4341 SetReadoutMode(1);
4342 SetInputRange(r);
4343 if (fBoardType == 5)
4344 SelectClockSource(0);
4345 else if (fBoardType == 6)
4346 SetRefclk(refclk);
4347 EnableTrigger(0, 0);
4348
4349 StartDomino();
4350
4351 nChan = 0;
4352
4353 if (fBoardType == 5) {
4354 nChan = 9;
4355 timingChan = 8;
4356
4357 /* measure offset */
4358 EnableAcal(0, 0); // no inputs signal is allowed during calibration!
4359 EnableTcal(0, 0);
4360 Sleep(100);
4361 RobustAverageWaveforms(pcb, 1, nChan, 0, 33, wf1[0], 500, true);
4362
4363 /* measure gain at upper range */
4364 EnableAcal(1, fRange+0.4);
4365 EnableTcal(0, 1);
4366 Sleep(100);
4367 RobustAverageWaveforms(pcb, 1, nChan, 33, 66, wf2[0], 500, true);
4368
4369 } else if (fBoardType == 6) {
4370 if (fTransport == TR_USB2) {
4371 nChan = 36;
4372 timingChan = 8;
4373 memset(wf1, 0, sizeof(wf1));
4374 memset(wf2, 0, sizeof(wf2));
4375 memset(wf3, 0, sizeof(wf3));
4376 for (config=p=0 ; config<4 ; config++) {
4377 SetChannelConfig(config, 8, 8);
4378
4379 /* measure offset */
4380 EnableAcal(1, 0);
4381 EnableTcal(0, 0);
4382 Sleep(100);
4383 RobustAverageWaveforms(pcb, 0, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
4384 for (i=0 ; i<5 ; i++)
4385 memcpy(wf1[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
4386 RobustAverageWaveforms(pcb, 2, 10, F1(p), F1(p+1), wft[0], 500, true); p++;
4387 for (i=0 ; i<5 ; i++)
4388 memcpy(wf1[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
4389
4390 /* measure gain at +400 mV */
4391 EnableAcal(1, 0.4);
4392 EnableTcal(0, 0);
4393 Sleep(100);
4394 RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
4395 for (i=0 ; i<4 ; i++)
4396 memcpy(wf2[idx[config][i]], wft[i*2], sizeof(float)*kNumberOfBins);
4397 RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
4398 for (i=0 ; i<4 ; i++)
4399 memcpy(wf2[idx[config][i+5]], wft[i*2], sizeof(float)*kNumberOfBins);
4400
4401 /* measure gain at -400 mV */
4402 EnableAcal(1, -0.4);
4403 EnableTcal(0, 1);
4404 Sleep(100);
4405 RobustAverageWaveforms(pcb, 0, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
4406 for (i=0 ; i<4 ; i++)
4407 memcpy(wf3[idx[config][i]], wft[i], sizeof(float)*kNumberOfBins);
4408 RobustAverageWaveforms(pcb, 2, 8, F1(p), F1(p+1), wft[0], 500, true); p++;
4409 for (i=0 ; i<4 ; i++)
4410 memcpy(wf3[idx[config][i+5]], wft[i], sizeof(float)*kNumberOfBins);
4411 }
4412 } else {
4413 nChan = 36;
4414 timingChan = 8;
4415
4416 /* measure offset */
4417 EnableAcal(0, 0); // no inputs signal is allowed during calibration!
4418 EnableTcal(0, 0);
4419 Sleep(100);
4420 RobustAverageWaveforms(pcb, 4, 9, 0, 25, wf1[0], 500, true);
4421
4422 /* measure gain at upper range */
4423 EnableAcal(1, fRange+0.4);
4424 EnableTcal(0, 0);
4425 Sleep(100);
4426 RobustAverageWaveforms(pcb, 4, 9, 25, 50, wf2[0], 500, true);
4427 }
4428 }
4429
4430 /* convert offsets and gains to 16-bit values */
4431 memset(fCellOffset, 0, sizeof(fCellOffset));
4432 n_stuck = 0;
4433 for (i=0 ; i<nChan ; i++) {
4434 for (j=0 ; j<kNumberOfBins; j++) {
4435 if (i % 9 == timingChan) {
4436 /* calculate offset and gain for timing channel */
4437 if (fBoardType == 5) {
4438 /* we have a +325mV and a -325mV value */
4439 fCellOffset[i][j] = (unsigned short) ((wf1[i][j]+wf2[i][j])/2+0.5);
4440 fCellGain[i][j] = (wf2[i][j] - wf1[i][j])/65536.0*1000 / 650.0;
4441 } else {
4442 /* only have offset */
4443 fCellOffset[i][j] = wf1[i][j];
4444 fCellGain[i][j] = 1;
4445 }
4446 } else {
4447 /* calculate offset and gain for data channel */
4448 fCellOffset[i][j] = wf1[i][j];
4449 if (fCellOffset[i][j] < 100) {
4450 // mark stuck pixel
4451 n_stuck ++;
4452 fCellOffset[i][j] = 0;
4453 fCellGain[i][j] = 1;
4454 } else
4455 fCellGain[i][j] = (wf2[i][j] - fCellOffset[i][j])/65536.0*1000 / ((0.4+fRange)*1000);
4456 }
4457
4458 /* check gain */
4459 if (fCellGain[i][j] < 0.5 || fCellGain[i][j] > 1.1) {
4460 printf("Gain of %6.3lf for channel %2d, cell %4d out of range 0.5 ... 1.1\n",
4461 fCellGain[i][j], i, j);
4462 fCellGain[i][j] = 1;
4463 }
4464 }
4465 }
4466
4467 /*
4468 FILE *fh = fopen("calib.txt", "wt");
4469 for (i=0 ; i<nChan ; i++) {
4470 fprintf(fh, "CH%02d:", i);
4471 for (j=0 ; j<20 ; j++)
4472 fprintf(fh, " %5d", fCellOffset[i][j]-32768);
4473 fprintf(fh, "\n");
4474 }
4475 fclose(fh);
4476 */
4477
4478 /* perform secondary calibration */
4479 if (fBoardType == 5) {
4480 nChan = 9;
4481 timingChan = 8;
4482
4483 /* measure offset */
4484 EnableAcal(0, 0); // no inputs signal is allowed during calibration!
4485 EnableTcal(0, 0);
4486 Sleep(100);
4487 AverageWaveforms(pcb, 1, 9, 66, 100, wf1[0], 500, false);
4488 } else if (fBoardType == 6 && fTransport == TR_VME) {
4489 nChan = 36;
4490 timingChan = 8;
4491
4492 /* measure offset */
4493 EnableAcal(0, 0); // no inputs signal is allowed during calibration!
4494 EnableTcal(0, 0);
4495 Sleep(100);
4496 AverageWaveforms(pcb, 4, 9, 50, 75, wf1[0], 500, false);
4497 }
4498
4499 /* convert offset to 16-bit values */
4500 memset(fCellOffset2, 0, sizeof(fCellOffset2));
4501 for (i=0 ; i<nChan ; i++)
4502 for (j=0 ; j<kNumberOfBins; j++)
4503 if (i % 9 != timingChan)
4504 fCellOffset2[i][j] = wf1[i][j];
4505
4506 /*
4507 FILE *fh = fopen("calib.txt", "wt");
4508 for (i=0 ; i<nChan ; i++) {
4509 for (j=0 ; j<kNumberOfBins; j++)
4510 fprintf(fh, "%5d: %5d %5d\n", j, fCellOffset2[0][j]-32768, fCellOffset2[1][j]-32768);
4511 fprintf(fh, "\n");
4512 }
4513 fclose(fh);
4514 */
4515
4516 if (fBoardType == 5) {
4517 /* write calibration CH0-CH7 to EEPROM page 1 */
4518 for (i=0 ; i<8 ; i++)
4519 for (j=0 ; j<1024; j++) {
4520 buf[(i*1024+j)*2] = fCellOffset[i][j];
4521 buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i][j] - 0.7) / 0.4 * 65535);
4522 }
4523 WriteEEPROM(1, buf, 1024*32);
4524
4525 /* write calibration CH8 and secondary calibration to EEPROM page 2 */
4526 ReadEEPROM(2, buf, 1024*5*4);
4527 for (j=0 ; j<1024; j++) {
4528 buf[j*2] = fCellOffset[8][j];
4529 buf[j*2+1] = (unsigned short) ((fCellGain[8][j] - 0.7) / 0.4 * 65535);
4530 }
4531 for (i=0 ; i<4 ; i++)
4532 for (j=0 ; j<1024; j++) {
4533 buf[2*1024+((i*2)*1024+j)*2] = fCellOffset2[i*2][j];
4534 buf[2*1024+((i*2)*1024+j)*2+1] = fCellOffset2[i*2+1][j];
4535 }
4536 WriteEEPROM(2, buf, 1024*5*4);
4537
4538 /* write calibration method and range */
4539 ReadEEPROM(0, buf, 2048); // 0-0x0FFF
4540 buf[2] = VCALIB_METHOD | ((signed char)(fRange * 100)) << 8;
4541 WriteEEPROM(0, buf, 2048);
4542 fCellCalibratedRange = fRange;
4543
4544 } else if (fBoardType == 6) {
4545 for (chip=0 ; chip<4 ; chip++) {
4546 /* write calibration of A0 to A7 to EEPROM page 1
4547 B0 to B7 to EEPROM page 2 and so on */
4548 for (i=0 ; i<8 ; i++)
4549 for (j=0 ; j<1024; j++) {
4550 buf[(i*1024+j)*2] = fCellOffset[i+chip*9][j];
4551 buf[(i*1024+j)*2+1] = (unsigned short) ((fCellGain[i+chip*9][j] - 0.7) / 0.4 * 65535);
4552 }
4553 WriteEEPROM(1+chip, buf, 1024*32);
4554 if (pcb != NULL)
4555 pcb->Progress(75+chip*4);
4556 }
4557
4558 /* write calibration A/B/C/D/CLK to EEPROM page 5 */
4559 ReadEEPROM(5, buf, 1024*4*4);
4560 for (chip=0 ; chip<4 ; chip++) {
4561 for (j=0 ; j<1024; j++) {
4562 buf[j*2+chip*0x0800] = fCellOffset[8+chip*9][j];
4563 buf[j*2+1+chip*0x0800] = (unsigned short) ((fCellGain[8+chip*9][j] - 0.7) / 0.4 * 65535);
4564 }
4565 }
4566 WriteEEPROM(5, buf, 1024*4*4);
4567 if (pcb != NULL)
4568 pcb->Progress(90);
4569
4570 /* write secondary calibration to EEPROM page 7 and 8 */
4571 for (i=0 ; i<8 ; i++) {
4572 for (j=0 ; j<1024; j++) {
4573 buf[i*0x800 + j*2] = fCellOffset2[i][j];
4574 buf[i*0x800 + j*2+1] = fCellOffset2[i+9][j];
4575 }
4576 }
4577 WriteEEPROM(7, buf, 1024*32);
4578 if (pcb != NULL)
4579 pcb->Progress(94);
4580
4581 for (i=0 ; i<8 ; i++) {
4582 for (j=0 ; j<1024; j++) {
4583 buf[i*0x800 + j*2] = fCellOffset2[i+18][j];
4584 buf[i*0x800 + j*2+1] = fCellOffset2[i+27][j];
4585 }
4586 }
4587 WriteEEPROM(8, buf, 1024*32);
4588 if (pcb != NULL)
4589 pcb->Progress(98);
4590
4591 /* write calibration method and range */
4592 ReadEEPROM(0, buf, 2048); // 0-0x0FFF
4593 buf[2] = VCALIB_METHOD | ((signed char)(fRange * 100)) << 8;
4594 WriteEEPROM(0, buf, 2048);
4595 fCellCalibratedRange = fRange;
4596 if (pcb != NULL)
4597 pcb->Progress(100);
4598 }
4599
4600 if (n_stuck)
4601 printf("\nFound %d stuck pixels on this board\n", n_stuck);
4602
4603 fCellCalibrationValid = true;
4604
4605 /* remove calibration voltage */
4606 EnableAcal(0, 0);
4607 EnableTcal(0, 0);
4608 EnableTrigger(trg1, trg2);
4609
4610 return 1;
4611}
4612
4613/*------------------------------------------------------------------*/
4614
4615int DRSBoard::AnalyzeWF(int nIter, float wf[kNumberOfBins], int tCell, double cellT[kNumberOfBins])
4616{
4617int i, i1, i2, j, k, nzx, zeroXing[1000], edge, n_correct;
4618double damping, zeroLevel, ta, tb, dt, corr, inv_corr;
4619
4620 /* calculate zero level */
4621 for (i=0,zeroLevel=0 ; i<1024 ; i++)
4622 zeroLevel += wf[i];
4623 zeroLevel /= 1024;
4624
4625 /* correct for zero common mode */
4626 for (i=0 ; i<1024 ; i++)
4627 wf[i] -= (float)zeroLevel;
4628
4629 /* estimate damping factor */
4630 damping = fFrequency / nIter * 40;
4631
4632 for (edge = 0 ; edge < 2 ; edge ++) {
4633
4634 /* find edge zero crossing with wrap-around */
4635 for (i=tCell+3,nzx=0 ; i<tCell+1023 && nzx < (int)(sizeof(zeroXing)/sizeof(int)) ; i++) {
4636 if (edge == 0) {
4637 if (wf[(i+1) % 1024] < 0 && wf[i % 1024] > 0) // falling edge
4638 zeroXing[nzx++] = i;
4639 } else {
4640 if (wf[(i+1) % 1024] > 0 && wf[i % 1024] < 0) // rising edge
4641 zeroXing[nzx++] = i;
4642 }
4643 }
4644
4645 if (nzx < 20)
4646 return 0;
4647
4648 for (i=n_correct=0 ; i<nzx-1 ; i++) {
4649 i1 = zeroXing[i] % 1024;
4650 if (i1 == 1023)
4651 continue;
4652 ta = cellT[i1] + (cellT[i1+1] - cellT[i1])*(1/(1-wf[(i1+1) % 1024]/wf[i1]));
4653 i2 = zeroXing[i+1] % 1024;
4654 if (i2 == 1023)
4655 continue;
4656 tb = cellT[i2] + (cellT[i2+1] - cellT[i2])*(1/(1-wf[(i2+1) % 1024]/wf[i2]));
4657
4658// for (i=n_correct=0 ; i<nzx-1 ; i++) {
4659 // i1 = zeroXing[i] % 1024;
4660 // ta = cellT[i1] + (cellT[i1+1] - cellT[i1])*(1/(1-wf[(i1+1)%1024]/wf[i1]));
4661// i2 = zeroXing[i+1] % 1024;
4662// tb = cellT[i2] + (cellT[i2+1] - cellT[i2])*(1/(1-wf[(i2+1)%1024]/wf[i2]));
4663
4664 /* wrap-around ? */
4665 if (tb - ta < 0)
4666 tb += 1/fFrequency*1024;
4667
4668 /* calculate correction to nominal period in ns */
4669 corr = 1/fTCALFrequency*1000 - (tb - ta);
4670
4671 /* skip very large corrections (noise?) */
4672 if (fabs(corr/(1/fTCALFrequency*1000)) > 0.5)
4673 continue;
4674
4675 /* remeber number of valid corrections */
4676 n_correct++;
4677
4678 /* apply damping factor */
4679 corr *= damping;
4680
4681 /* calculate inverse correction */
4682 inv_corr = -corr;
4683
4684 /* apply from (i1+1)+1 to i2 inclusive */
4685 i1 = zeroXing[i]+2;
4686 i2 = zeroXing[i+1];
4687
4688 /* distribute correciton equally into bins inside the region ... */
4689 corr = corr / (i2-i1+1);
4690
4691 /* ... and inverse correction into the outside bins */
4692 inv_corr = inv_corr / (1024 - (i2-i1+1));
4693
4694 i1 = i1 % 1024;
4695 i2 = i2 % 1024;
4696
4697 double oldT[kNumberOfBins];
4698 memcpy(oldT, cellT, sizeof(double)*1024);
4699 for (j=0,ta=0 ; j<1024 ; j++) {
4700 if (j < 1023)
4701 dt = cellT[j+1] - cellT[j];
4702 else
4703 dt = 1/fFrequency*1024 - cellT[j];
4704 if ((i2 > i1 && (j >= i1 && j<= i2)) ||
4705 (i2 < i1 && (j >= i1 || j<= i2)) )
4706 dt += corr;
4707 else
4708 dt += inv_corr;
4709
4710 cellT[j] = ta;
4711 ta += dt;
4712 }
4713
4714 /* check and correct for too narrow bin widths */
4715 for (j=0 ; j<1023 ; j++) {
4716 dt = cellT[j+1] - cellT[j];
4717 if (dt < 1/fFrequency*0.1) {
4718 /* if width is smaller than 10% of nominal width, "undo" 5x that correction,
4719 otherwise next iteration would cause this problem again */
4720 corr = 5*(1/fFrequency*0.1-dt);
4721 inv_corr = -corr;
4722
4723 /* distribute inverse correction equally into the outside bins */
4724 inv_corr = inv_corr / 1022;
4725
4726 for (k=0,ta=0 ; k<1024 ; k++) {
4727 if (k < 1023)
4728 dt = cellT[k+1] - cellT[k];
4729 else
4730 dt = 1/fFrequency*1024 - cellT[k];
4731 if (k == j)
4732 dt += corr;
4733 else
4734 dt += inv_corr;
4735
4736 cellT[k] = ta;
4737 ta += dt;
4738 }
4739 }
4740 }
4741 }
4742
4743 if (n_correct < nzx/3)
4744 return 0;
4745 }
4746
4747 return 1;
4748}
4749
4750/*------------------------------------------------------------------*/
4751
4752
4753int DRSBoard::CalibrateTiming(DRSCallback *pcb)
4754{
4755int index, status, tCell, i, c, chip, mode, nIter, clkon, phase, refclk, trg1, trg2;
4756double f, range, t1[4], t2[4];
4757unsigned short buf[1024*4];
4758float wf[1024];
4759
4760 nIter = 1000;
4761 f = fFrequency;
4762 range = fRange;
4763 clkon = (GetCtrlReg() & BIT_TCAL_EN) > 0;
4764 refclk = (GetCtrlReg() & BIT_REFCLK_SOURCE) > 0;
4765 trg1 = fTriggerEnable1;
4766 trg2 = fTriggerEnable2;
4767
4768 Init();
4769 fFrequency = f;
4770 SetRefclk(refclk);
4771 SetFrequency(fFrequency, true);
4772 if (fBoardType == 5)
4773 fTCALFrequency = 240; // 240 MHz, for MEZZ this is set by ConfigureLMK
4774 SetDominoMode(1);
4775 SetDominoActive(1);
4776 SetReadoutMode(1);
4777 EnableTrigger(0, 0);
4778 EnableTcal(1, 0, 0);
4779 if (fBoardType == 5)
4780 SelectClockSource(1); // 2nd quartz
4781 StartDomino();
4782
4783 /* initialize time array */
4784 for (i=0 ; i<1024 ; i++)
4785 for (chip=0 ; chip<4 ; chip++)
4786 fCellT[chip][i] = (float)1/fFrequency*i; // [ns]
4787
4788 for (index = 0 ; index < nIter ; index++) {
4789 if (index % 10 == 0)
4790 pcb->Progress(100*index/nIter);
4791
4792 if (fTransport == TR_VME) {
4793 SoftTrigger();
4794 while (IsBusy());
4795
4796 /* select random phase */
4797 phase = (rand() % 30) - 15;
4798 if (phase == 0)
4799 phase = 15;
4800 EnableTcal(1, 0, phase);
4801
4802 StartDomino();
4803 TransferWaves();
4804
4805 for (chip=0 ; chip<4 ; chip++) {
4806 tCell = GetStopCell(chip);
4807 GetWave(chip, 8, wf, true, tCell, true);
4808 status = AnalyzeWF(nIter, wf, tCell, fCellT[chip]);
4809
4810 if (!status)
4811 return 0;
4812 }
4813 } else {
4814 if (fBoardType == 5) { // DRS4 Evaluation board: 1 Chip
4815 SoftTrigger();
4816 while (IsBusy());
4817
4818 StartDomino();
4819 TransferWaves();
4820
4821 tCell = GetStopCell(0);
4822 GetWave(0, 8, wf, true, tCell, true);
4823 status = AnalyzeWF(nIter, wf, tCell, fCellT[0]);
4824
4825 if (!status)
4826 return 0;
4827
4828 } else { // DRS4 Mezzanine board: 4 Chips
4829 for (mode=0 ; mode<2 ; mode++) {
4830 SetChannelConfig(mode*2, 8, 8);
4831 SoftTrigger();
4832 while (IsBusy());
4833
4834 /* select random phase */
4835 phase = (rand() % 30) - 15;
4836 if (phase == 0)
4837 phase = 15;
4838 EnableTcal(1, 0, phase);
4839
4840 StartDomino();
4841 TransferWaves();
4842
4843 for (chip=0 ; chip<4 ; chip+=2) {
4844 tCell = GetStopCell(chip+mode);
4845 GetWave(chip+mode, 8, wf, true, tCell, true);
4846 status = AnalyzeWF(nIter, wf, tCell, fCellT[chip+mode]);
4847
4848 if (!status)
4849 return 0;
4850 }
4851 }
4852 }
4853 }
4854 }
4855
4856 pcb->Progress(100);
4857
4858 // use following lines to save calibration into an ASCII file
4859#if 0
4860 FILE *fh;
4861
4862 fh = fopen("cellt.csv", "wt");
4863 if (!fh)
4864 printf("Cannot open file \"cellt.csv\"\n");
4865 else {
4866 fprintf(fh, "index;d_ch1;d_ch2;d_ch3;d_ch4\n");
4867 for (i=0 ; i<1024 ; i++)
4868 fprintf(fh, "%4d;%5.3lf;%5.3lf;%5.3lf;%5.3lf\n", i,
4869 fCellT[0][i]-i/fFrequency,
4870 fCellT[1][i]-i/fFrequency,
4871 fCellT[2][i]-i/fFrequency,
4872 fCellT[3][i]-i/fFrequency);
4873 fclose(fh);
4874 }
4875#endif
4876
4877 if (fBoardType == 5) {
4878 /* write timing calibration to EEPROM page 0 */
4879 ReadEEPROM(0, buf, sizeof(buf));
4880 for (i=0,t1[0]=0 ; i<1024; i++) {
4881 t2[0] = fCellT[0][i] - t1[0];
4882 t2[0] = (unsigned short) (t2[0] * 10000 + 0.5);
4883 t1[0] += t2[0] / 10000.0;
4884 buf[i*2+1] = (unsigned short) t2[0];
4885 }
4886
4887 /* write calibration method and frequency */
4888 buf[4] = TCALIB_METHOD;
4889 buf[6] = (unsigned short) (fFrequency / 6.0 * 65535.0);
4890 fTimingCalibratedFrequency = buf[6] / 65535.0 * 6.0;
4891 WriteEEPROM(0, buf, sizeof(buf));
4892 } else {
4893 /* write timing calibration to EEPROM page 6 */
4894 ReadEEPROM(6, buf, sizeof(buf));
4895 for (c=0 ; c<4 ; c++)
4896 t1[c] = 0;
4897 for (i=0 ; i<1024; i++) {
4898 for (c=0 ; c<4 ; c++) {
4899 t2[c] = fCellT[c][i] - t1[c];
4900 t2[c] = (unsigned short) (t2[c] * 10000 + 0.5);
4901 t1[c] += t2[c] / 10000.0;
4902 }
4903 buf[i*2] = (unsigned short) t2[0];
4904 buf[i*2+1] = (unsigned short) t2[1];
4905 buf[i*2+0x800] = (unsigned short) t2[2];
4906 buf[i*2+0x800+1] = (unsigned short) t2[3];
4907 }
4908 WriteEEPROM(6, buf, sizeof(buf));
4909
4910 /* write calibration method and frequency */
4911 ReadEEPROM(0, buf, 16);
4912 buf[4] = TCALIB_METHOD;
4913 buf[6] = (unsigned short) (fFrequency / 6.0 * 65535.0);
4914 fTimingCalibratedFrequency = buf[6] / 65535.0 * 6.0;
4915 WriteEEPROM(0, buf, 16);
4916 }
4917
4918 fTimingCalibrationValid = true;
4919
4920 /* remove calibration voltage */
4921 EnableAcal(0, 0);
4922 EnableTcal(clkon, 0);
4923 SetInputRange(range);
4924 EnableTrigger(trg1, trg2);
4925
4926 return 1;
4927}
4928
4929
4930/*------------------------------------------------------------------*/
4931
4932
4933void DRSBoard::RemoveSymmetricSpikes(short **wf, int nwf,
4934 short diffThreshold, int spikeWidth,
4935 short maxPeakToPeak, short spikeVoltage,
4936 int nTimeRegionThreshold)
4937{
4938 // Remove a specific kind of spike on DRS4.
4939 // This spike has some features,
4940 // - Common on all the channels on a chip
4941 // - Constant heigh and width
4942 // - Two spikes per channel
4943 // - Symmetric to cell #0.
4944 //
4945 // This is not general purpose spike-removing function.
4946 //
4947 // wf : Waveform data. cell#0 must be at bin0,
4948 // and number of bins must be kNumberOfBins.
4949 // nwf : Number of channels which "wf" holds.
4950 // diffThreshold : Amplitude threshold to find peak
4951 // spikeWidth : Width of spike
4952 // maxPeakToPeak : When peak-to-peak is larger than this, the channel
4953 // is not used to find spikes.
4954 // spikeVoltage : Amplitude of spikes. When it is 0, it is calculated in this function
4955 // from voltage difference from neighboring bins.
4956 // nTimeRegionThreshold : Requirement of number of time regions having spike at common position.
4957 // Total number of time regions is 2*"nwf".
4958
4959 if (!wf || !nwf || !diffThreshold || !spikeWidth) {
4960 return;
4961 }
4962
4963 int ibin, jbin, kbin;
4964 double v;
4965 int nbin;
4966 int iwf;
4967 short maximum, minimum;
4968 int spikeCount[kNumberOfBins / 2];
4969 int spikeCountSum[kNumberOfBins / 2] = {0};
4970 bool largePulse[kNumberOfChannelsMax * 2] = {0};
4971 const short diffThreshold2 = diffThreshold + diffThreshold;
4972
4973 const short maxShort = 0xFFFF>>1;
4974 const short minShort = -maxShort - 1;
4975
4976 // search spike
4977 for (iwf = 0; iwf < nwf; iwf++) {
4978 // first half
4979 memset(spikeCount, 0, sizeof(spikeCount));
4980 maximum = minShort;
4981 minimum = maxShort;
4982 for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
4983 jbin = ibin;
4984 maximum = max(maximum, wf[iwf][jbin]);
4985 minimum = min(minimum, wf[iwf][jbin]);
4986 if (jbin - 1 >= 0 && jbin + spikeWidth < kNumberOfBins) {
4987 v = 0;
4988 nbin = 0;
4989 for (kbin = 0; kbin < spikeWidth; kbin++) {
4990 v += wf[iwf][jbin + kbin];
4991 nbin++;
4992 }
4993 if ((nbin == 2 && v - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) > diffThreshold2) ||
4994 (nbin != 2 && nbin && v / nbin - (wf[iwf][jbin - 1] + wf[iwf][jbin + spikeWidth]) / 2 > diffThreshold)) {
4995 spikeCount[ibin]++;
4996 }
4997 }
4998 }
4999 if (maximum != minShort && minimum != maxShort &&
5000 (!maxPeakToPeak || maximum - minimum < maxPeakToPeak)) {
5001 for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
5002 spikeCountSum[ibin] += spikeCount[ibin];
5003 }
5004 largePulse[iwf] = false;
5005#if 0 /* this part can be enabled to skip checking other channels */
5006 if (maximum != minShort && minimum != maxShort &&
5007 maximum - minimum < diffThreshold) {
5008 return;
5009 }
5010#endif
5011 } else {
5012 largePulse[iwf] = true;
5013 }
5014
5015 // second half
5016 memset(spikeCount, 0, sizeof(spikeCount));
5017 maximum = minShort;
5018 minimum = maxShort;
5019 for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
5020 jbin = kNumberOfBins - 1 - ibin;
5021 maximum = max(maximum, wf[iwf][jbin]);
5022 minimum = min(minimum, wf[iwf][jbin]);
5023 if (jbin + 1 < kNumberOfBins && jbin - spikeWidth >= 0) {
5024 v = 0;
5025 nbin = 0;
5026 for (kbin = 0; kbin < spikeWidth; kbin++) {
5027 v += wf[iwf][jbin - kbin];
5028 nbin++;
5029 }
5030 if ((nbin == 2 && v - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) > diffThreshold2) ||
5031 (nbin != 2 && nbin && v / nbin - (wf[iwf][jbin + 1] + wf[iwf][jbin - spikeWidth]) / 2 > diffThreshold)) {
5032 spikeCount[ibin]++;
5033 }
5034 }
5035 }
5036 if (maximum != minShort && minimum != maxShort &&
5037 maximum - minimum < maxPeakToPeak) {
5038 for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
5039 spikeCountSum[ibin] += spikeCount[ibin];
5040 }
5041 largePulse[iwf + nwf] = false;
5042#if 0 /* this part can be enabled to skip checking other channels */
5043 if (maximum != minShort && minimum != maxShort &&
5044 maximum - minimum < diffThreshold) {
5045 return;
5046 }
5047#endif
5048 } else {
5049 largePulse[iwf + nwf] = true;
5050 }
5051 }
5052
5053 // Find common spike
5054 int commonSpikeBin = -1;
5055 int commonSpikeMax = -1;
5056 for (ibin = 0; ibin < kNumberOfBins / 2; ibin++) {
5057 if (commonSpikeMax < spikeCountSum[ibin]) {
5058 commonSpikeMax = spikeCountSum[ibin];
5059 commonSpikeBin = ibin;
5060 }
5061 }
5062
5063 if (spikeCountSum[commonSpikeBin] >= nTimeRegionThreshold) {
5064 if (spikeVoltage == 0) {
5065 // Estimate spike amplitude
5066 double baseline = 0;
5067 int nBaseline = 0;
5068 double peakAmplitude = 0;
5069 int nPeakAmplitude = 0;
5070 for (iwf = 0; iwf < nwf; iwf++) {
5071 // first half
5072 if (!largePulse[iwf]) {
5073 // baseline
5074 if ((jbin = commonSpikeBin - 1) >= 0 && jbin < kNumberOfBins) {
5075 baseline += wf[iwf][jbin];
5076 nBaseline++;
5077 }
5078 if ((jbin = commonSpikeBin + spikeWidth + 1) >= 0 && jbin < kNumberOfBins) {
5079 baseline += wf[iwf][jbin];
5080 nBaseline++;
5081 }
5082 // spike
5083 for (ibin = 0; ibin < spikeWidth; ibin++) {
5084 if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
5085 peakAmplitude += wf[iwf][jbin];
5086 nPeakAmplitude++;
5087 }
5088 }
5089 }
5090
5091 // second half
5092 if (!largePulse[iwf + nwf]) {
5093 // baseline
5094 if ((jbin = kNumberOfBins - 1 - commonSpikeBin + 1) >= 0 && jbin < kNumberOfBins) {
5095 baseline += wf[iwf][jbin];
5096 nBaseline++;
5097 }
5098 if ((jbin = kNumberOfBins - 1 - commonSpikeBin - spikeWidth - 1) >= 0 && jbin < kNumberOfBins) {
5099 baseline += wf[iwf][jbin];
5100 nBaseline++;
5101 }
5102 // spike
5103 for (ibin = 0; ibin < spikeWidth; ibin++) {
5104 if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
5105 peakAmplitude += wf[iwf][jbin];
5106 nPeakAmplitude++;
5107 }
5108 }
5109 }
5110 }
5111 if (nBaseline && nPeakAmplitude) {
5112 baseline /= nBaseline;
5113 peakAmplitude /= nPeakAmplitude;
5114 spikeVoltage = static_cast<short>(peakAmplitude - baseline);
5115 } else {
5116 spikeVoltage = 0;
5117 }
5118 }
5119
5120 // Remove spike
5121 if (spikeVoltage > 0) {
5122 for (iwf = 0; iwf < nwf; iwf++) {
5123 for (ibin = 0; ibin < spikeWidth; ibin++) {
5124 if ((jbin = commonSpikeBin + ibin) >= 0 && jbin < kNumberOfBins) {
5125 wf[iwf][jbin] -= spikeVoltage;
5126 }
5127 if ((jbin = kNumberOfBins - 1 - commonSpikeBin - ibin) >= 0 && jbin < kNumberOfBins) {
5128 wf[iwf][jbin] -= spikeVoltage;
5129 }
5130 }
5131 }
5132 }
5133 }
5134}
5135
5136/*------------------------------------------------------------------*/
5137
5138void ResponseCalibration::SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints,
5139 int numberOfMode2Bins, int numberOfSamples,
5140 int numberOfGridPoints, int numberOfXConstPoints,
5141 int numberOfXConstGridPoints, double triggerFrequency,
5142 int showStatistics)
5143{
5144 DeleteFields();
5145 InitFields(numberOfPointsLowVolt, numberOfPoints, numberOfMode2Bins, numberOfSamples, numberOfGridPoints,
5146 numberOfXConstPoints, numberOfXConstGridPoints, triggerFrequency, showStatistics);
5147}
5148
5149/*------------------------------------------------------------------*/
5150
5151void ResponseCalibration::ResetCalibration()
5152{
5153 int i;
5154 for (i = 0; i < kNumberOfChipsMax; i++)
5155 fCalibrationData[i]->fRead = false;
5156 fCurrentPoint = 0;
5157 fCurrentLowVoltPoint = 0;
5158 fCurrentSample = 0;
5159 fCurrentFitChannel = 0;
5160 fCurrentFitBin = 0;
5161 fRecorded = false;
5162 fFitted = false;
5163 fOffset = false;
5164};
5165
5166/*------------------------------------------------------------------*/
5167
5168bool ResponseCalibration::WriteCalibration(unsigned int chipIndex)
5169{
5170 if (!fOffset)
5171 return false;
5172 if (fBoard->GetDRSType() == 3)
5173 return WriteCalibrationV4(chipIndex);
5174 else
5175 return WriteCalibrationV3(chipIndex);
5176}
5177
5178/*------------------------------------------------------------------*/
5179
5180bool ResponseCalibration::WriteCalibrationV3(unsigned int chipIndex)
5181{
5182 if (!fOffset)
5183 return false;
5184
5185 int ii, j, k;
5186 char str[1000];
5187 char strt[1000];
5188 short tempShort;
5189 CalibrationData *data = fCalibrationData[chipIndex];
5190 CalibrationData::CalibrationDataChannel * chn;
5191
5192 // Open File
5193 fBoard->GetCalibrationDirectory(strt);
5194 sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
5195 if (MakeDir(str) == -1) {
5196 printf("Error: Cannot create directory \"%s\"\n", str);
5197 return false;
5198 }
5199 sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
5200 fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetFrequency() * 1000));
5201 fCalibFile = fopen(str, "wb");
5202 if (fCalibFile == NULL) {
5203 printf("Error: Cannot write to file \"%s\"\n", str);
5204 return false;
5205 }
5206 // Write File
5207 fwrite(&data->fNumberOfGridPoints, 1, 1, fCalibFile);
5208 tempShort = static_cast < short >(data->fStartTemperature) * 10;
5209 fwrite(&tempShort, 2, 1, fCalibFile);
5210 tempShort = static_cast < short >(data->fEndTemperature) * 10;
5211 fwrite(&tempShort, 2, 1, fCalibFile);
5212 fwrite(&data->fMin, 4, 1, fCalibFile);
5213 fwrite(&data->fMax, 4, 1, fCalibFile);
5214 fwrite(&data->fNumberOfLimitGroups, 1, 1, fCalibFile);
5215
5216 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5217 chn = data->fChannel[ii];
5218 for (j = 0; j < kNumberOfBins; j++) {
5219 fwrite(&chn->fLimitGroup[j], 1, 1, fCalibFile);
5220 fwrite(&chn->fLookUpOffset[j], 2, 1, fCalibFile);
5221 fwrite(&chn->fNumberOfLookUpPoints[j], 1, 1, fCalibFile);
5222 for (k = 0; k < chn->fNumberOfLookUpPoints[j]; k++) {
5223 fwrite(&chn->fLookUp[j][k], 1, 1, fCalibFile);
5224 }
5225 for (k = 0; k < data->fNumberOfGridPoints; k++) {
5226 fwrite(&chn->fData[j][k], 2, 1, fCalibFile);
5227 }
5228 fwrite(&chn->fOffsetADC[j], 2, 1, fCalibFile);
5229 fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
5230 }
5231 }
5232 fclose(fCalibFile);
5233
5234 printf("Calibration successfully written to\n\"%s\"\n", str);
5235 return true;
5236}
5237
5238/*------------------------------------------------------------------*/
5239
5240bool ResponseCalibration::WriteCalibrationV4(unsigned int chipIndex)
5241{
5242 if (!fOffset)
5243 return false;
5244
5245 int ii, j;
5246 char str[1000];
5247 char strt[1000];
5248 CalibrationData *data = fCalibrationData[chipIndex];
5249 CalibrationData::CalibrationDataChannel * chn;
5250
5251 // Open File
5252 fBoard->GetCalibrationDirectory(strt);
5253 sprintf(str, "%s/board%d", strt, fBoard->GetBoardSerialNumber());
5254 if (MakeDir(str) == -1) {
5255 printf("Error: Cannot create directory \"%s\"\n", str);
5256 return false;
5257 }
5258 sprintf(str, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", strt, fBoard->GetBoardSerialNumber(),
5259 fBoard->GetBoardSerialNumber(), chipIndex, static_cast < int >(fBoard->GetFrequency() * 1000));
5260 fCalibFile = fopen(str, "wb");
5261 if (fCalibFile == NULL) {
5262 printf("Error: Cannot write to file \"%s\"\n", str);
5263 return false;
5264 }
5265 // Write File
5266 for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++) {
5267 chn = data->fChannel[ii];
5268 for (j = 0; j < kNumberOfBins; j++) {
5269 fwrite(&chn->fOffset[j], 2, 1, fCalibFile);
5270 fwrite(&chn->fGain[j], 2, 1, fCalibFile);
5271 }
5272 }
5273 fclose(fCalibFile);
5274
5275 printf("Calibration successfully written to\n\"%s\"\n", str);
5276 return true;
5277}
5278
5279/*------------------------------------------------------------------*/
5280
5281void ResponseCalibration::CalibrationTrigger(int mode, double voltage)
5282{
5283 fBoard->Reinit();
5284 fBoard->EnableAcal(mode, voltage);
5285 fBoard->StartDomino();
5286 fBoard->SoftTrigger();
5287 while (fBoard->IsBusy()) {
5288 }
5289}
5290
5291/*------------------------------------------------------------------*/
5292
5293void ResponseCalibration::CalibrationStart(double voltage)
5294{
5295 fBoard->SetDominoMode(1);
5296 fBoard->EnableAcal(0, voltage);
5297 fBoard->StartDomino();
5298 fBoard->IsBusy();
5299 fBoard->IsBusy();
5300 fBoard->IsBusy();
5301}
5302
5303/*------------------------------------------------------------------*/
5304
5305bool ResponseCalibration::RecordCalibrationPoints(int chipNumber)
5306{
5307 if (!fInitialized)
5308 return true;
5309 if (fBoard->GetDRSType() == 3)
5310 return RecordCalibrationPointsV4(chipNumber);
5311 else
5312 return RecordCalibrationPointsV3(chipNumber);
5313}
5314
5315/*------------------------------------------------------------------*/
5316
5317bool ResponseCalibration::RecordCalibrationPointsV3(int chipNumber)
5318{
5319 int j, k, ii;
5320 int notdone, nsample;
5321 double voltage;
5322 float mean;
5323 const double minVolt = 0.006;
5324 const double xpos[50] =
5325 { 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,
5326 0.277, 0.294, 0.310,
5327 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,
5328 0.656, 0.710,
5329 0.772, 0.842, 0.916,
5330 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
5331 };
5332
5333 // Initialisations
5334 if (fCurrentLowVoltPoint == 0) {
5335 fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0);
5336 // Record Temperature
5337 fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
5338 }
5339 // Record current Voltage
5340 if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
5341 voltage =
5342 (xpos[0] - minVolt) * fCurrentLowVoltPoint / static_cast <
5343 double >(fNumberOfPointsLowVolt) + minVolt;
5344 else
5345 voltage = xpos[fCurrentPoint];
5346 fBoard->SetCalibVoltage(voltage);
5347 fResponseY[fCurrentPoint + fCurrentLowVoltPoint] = static_cast < float >(voltage) * 1000;
5348
5349 // Loop Over Number Of Samples For Statistics
5350 for (j = 0; j < fNumberOfSamples; j++) {
5351 // Read Out Second Part of the Waveform
5352 CalibrationTrigger(3, voltage);
5353 fBoard->TransferWaves();
5354 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5355 fBoard->GetRawWave(chipNumber, ii, fWaveFormMode3[ii][j]);
5356 }
5357 // Read Out First Part of the Waveform
5358 CalibrationStart(voltage);
5359 CalibrationTrigger(2, voltage);
5360 fBoard->TransferWaves();
5361 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5362 fBoard->GetRawWave(chipNumber, ii, fWaveFormMode2[ii][j]);
5363 }
5364 CalibrationStart(voltage);
5365 }
5366 // Average Sample Points
5367 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5368 for (k = 0; k < kNumberOfBins; k++) {
5369 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = 0;
5370 for (j = 0; j < fNumberOfSamples; j++) {
5371 fSampleUsed[j] = 1;
5372 if (k < fNumberOfMode2Bins)
5373 fSamples[j] = fWaveFormMode2[ii][j][k];
5374 else
5375 fSamples[j] = fWaveFormMode3[ii][j][k];
5376 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] += fSamples[j];
5377 }
5378 mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / fNumberOfSamples;
5379 notdone = 1;
5380 nsample = fNumberOfSamples;
5381 while (notdone) {
5382 notdone = 0;
5383 for (j = 0; j < fNumberOfSamples; j++) {
5384 if (fSampleUsed[j] && abs(static_cast < int >(fSamples[j] - mean)) > 3) {
5385 notdone = 1;
5386 fSampleUsed[j] = 0;
5387 nsample--;
5388 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] -= fSamples[j];
5389 mean = fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] / nsample;
5390 }
5391 }
5392 }
5393 fResponseX[ii][k][fCurrentPoint + fCurrentLowVoltPoint] = mean;
5394 }
5395 }
5396 if (fCurrentLowVoltPoint < fNumberOfPointsLowVolt)
5397 fCurrentLowVoltPoint++;
5398 else
5399 fCurrentPoint++;
5400
5401 if (fCurrentPoint == fNumberOfPoints) {
5402 fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
5403 fRecorded = true;
5404 fFitted = false;
5405 fOffset = false;
5406 fCalibrationData[chipNumber]->fRead = false;
5407 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
5408 fBoard->SetCalibVoltage(0.0);
5409 fBoard->EnableAcal(1, 0.0);
5410 fBoard->SetDAC(fBoard->fDAC_CLKOFS, 0.0);
5411 return true;
5412 }
5413
5414 return false;
5415}
5416
5417/*------------------------------------------------------------------*/
5418
5419bool ResponseCalibration::RecordCalibrationPointsV4(int chipNumber)
5420{
5421 int i, j, k, n;
5422 double voltage, s, s2, average, sigma;
5423
5424 if (fCurrentPoint == 0) {
5425 fBoard->SetDominoMode(1);
5426 fBoard->EnableAcal(1, 0);
5427 fBoard->SoftTrigger();
5428 while (fBoard->IsBusy());
5429 fBoard->StartDomino();
5430 fCalibrationData[chipNumber]->fStartTemperature = static_cast < float >(fBoard->GetTemperature());
5431 }
5432 voltage = 1.0 * fCurrentPoint / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
5433 fBoard->SetCalibVoltage(voltage);
5434 Sleep(10);
5435 fBoard->SetCalibVoltage(voltage);
5436 Sleep(10);
5437
5438 // One dummy cycle for unknown reasons
5439 fBoard->SoftTrigger();
5440 while (fBoard->IsBusy());
5441 fBoard->StartDomino();
5442 Sleep(50);
5443 fBoard->TransferWaves();
5444
5445 // Loop over number of samples for statistics
5446 for (i = 0; i < fNumberOfSamples; i++) {
5447 if (fBoard->Debug()) {
5448 printf("%02d:%02d\r", fNumberOfPoints - fCurrentPoint, fNumberOfSamples - i);
5449 fflush(stdout);
5450 }
5451
5452
5453 fBoard->SoftTrigger();
5454 while (fBoard->IsBusy());
5455 fBoard->StartDomino();
5456 Sleep(50);
5457 fBoard->TransferWaves();
5458 for (j = 0; j < kNumberOfCalibChannelsV4; j++) {
5459 fBoard->GetRawWave(chipNumber, j, fWaveFormMode3[j][i]);
5460 }
5461 }
5462
5463 // Calculate averages
5464 for (i = 0; i < kNumberOfCalibChannelsV4; i++) {
5465 for (k = 0; k < kNumberOfBins; k++) {
5466 s = s2 = 0;
5467
5468 for (j = 0; j < fNumberOfSamples; j++) {
5469 s += fWaveFormMode3[i][j][k];
5470 s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
5471 }
5472 n = fNumberOfSamples;
5473 average = s / n;
5474 sigma = sqrt((n * s2 - s * s) / (n * (n - 1)));
5475
5476 fResponseX[i][k][fCurrentPoint] = static_cast < float >(average);
5477 }
5478 }
5479
5480#ifdef DEBUG_CALIB
5481 for (j = 0; j < fNumberOfSamples; j++)
5482 printf("%d ", fWaveFormMode3[1][j][10]);
5483
5484 s = s2 = 0;
5485 for (j = 0; j < fNumberOfSamples; j++) {
5486 s += fWaveFormMode3[i][j][k];
5487 s2 += fWaveFormMode3[i][j][k] * fWaveFormMode3[i][j][k];
5488 }
5489 n = fNumberOfSamples;
5490 average = s / n;
5491 sigma = sqrt((n * s2 - s * s) / (n * (n - 1)));
5492
5493 printf("\n");
5494 printf("%1.2lf V: %6.1lf (%1.4lf)\n", voltage,
5495 fResponseX[1][10][fCurrentPoint], fResponseX[1][10][fCurrentPoint] / 4096.0);
5496#endif
5497
5498 fCurrentPoint++;
5499 if (fCurrentPoint == fNumberOfPoints) {
5500 fCalibrationData[chipNumber]->fEndTemperature = static_cast < float >(fBoard->GetTemperature());
5501 fRecorded = true;
5502 return true;
5503 }
5504
5505 return false;
5506}
5507
5508/*------------------------------------------------------------------*/
5509
5510bool ResponseCalibration::FitCalibrationPoints(int chipNumber)
5511{
5512 if (!fRecorded || fFitted)
5513 return true;
5514 if (fBoard->GetDRSType() == 3)
5515 return FitCalibrationPointsV4(chipNumber);
5516 else
5517 return FitCalibrationPointsV3(chipNumber);
5518}
5519
5520/*------------------------------------------------------------------*/
5521
5522bool ResponseCalibration::FitCalibrationPointsV3(int chipNumber)
5523{
5524 int i, j, k;
5525 float x1, x2, y1, y2;
5526 float uu;
5527 float yc, yr;
5528 float xminExt, xrangeExt;
5529 float xmin, xrange;
5530 float average, averageError, averageExt, averageErrorExt;
5531 unsigned short i0, i1;
5532
5533 CalibrationData *data = fCalibrationData[chipNumber];
5534 CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
5535
5536 data->DeletePreCalculatedBSpline();
5537
5538 if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
5539 data->fNumberOfLimitGroups = 0;
5540 data->fMin = 100000;
5541 data->fMax = -100000;
5542 for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
5543 for (j = 0; j < kNumberOfBins; j++) {
5544 if (data->fMin > fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1])
5545 data->fMin = fResponseX[i][j][fNumberOfPointsLowVolt + fNumberOfPoints - 1];
5546 if (data->fMax < fResponseX[i][j][fNumberOfPointsLowVolt])
5547 data->fMax = fResponseX[i][j][fNumberOfPointsLowVolt];
5548 }
5549 }
5550 }
5551 // Low Volt
5552 i0 = static_cast < unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][0]);
5553 i1 = static_cast <
5554 unsigned short >(fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt]) + 1;
5555 chn->fLookUpOffset[fCurrentFitBin] = i0;
5556 delete chn->fLookUp[fCurrentFitBin];
5557 if (i0 - i1 + 1 < 2) {
5558 chn->fNumberOfLookUpPoints[fCurrentFitBin] = 2;
5559 chn->fLookUp[fCurrentFitBin] = new unsigned char[2];
5560 chn->fLookUp[fCurrentFitBin][0] = 0;
5561 chn->fLookUp[fCurrentFitBin][1] = 0;
5562 } else {
5563 chn->fNumberOfLookUpPoints[fCurrentFitBin] = i0 - i1 + 1;
5564 chn->fLookUp[fCurrentFitBin] = new unsigned char[i0 - i1 + 1];
5565 for (i = 0; i < i0 - i1 + 1; i++) {
5566 for (j = 0; j < fNumberOfPointsLowVolt; j++) {
5567 if (i0 - i >= fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1]) {
5568 x1 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j];
5569 x2 = fResponseX[fCurrentFitChannel][fCurrentFitBin][j + 1];
5570 y1 = fResponseY[j];
5571 y2 = fResponseY[j + 1];
5572 chn->fLookUp[fCurrentFitBin][i] =
5573 static_cast < unsigned char >(((y2 - y1) * (i0 - i - x1) / (x2 - x1) + y1) / fPrecision);
5574 break;
5575 }
5576 }
5577 }
5578 }
5579
5580 // Copy Points
5581 for (i = 0; i < fNumberOfPoints; i++) {
5582 fPntX[0][i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][fNumberOfPointsLowVolt + i];
5583 fPntY[0][i] = fResponseY[fNumberOfPointsLowVolt + i];
5584 }
5585 // Fit BSpline
5586 for (i = 0; i < fNumberOfPoints; i++) {
5587 fUValues[0][i] = static_cast < float >(1 - i / (fNumberOfPoints - 1.));
5588 }
5589 if (!Approx(fPntX[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fResX[fCurrentFitBin]))
5590 return true;
5591 if (!Approx(fPntY[0], fUValues[0], fNumberOfPoints, fNumberOfGridPoints, fRes[fCurrentFitBin]))
5592 return true;
5593
5594 // X constant fit
5595 for (k = 0; k < fNumberOfXConstPoints - 2; k++) {
5596 fPntX[1][k + 1] =
5597 GetValue(fResX[fCurrentFitBin],
5598 static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
5599 fNumberOfGridPoints);
5600 fPntY[1][k + 1] =
5601 GetValue(fRes[fCurrentFitBin],
5602 static_cast < float >(1 - k / static_cast < float >(fNumberOfXConstPoints - 3)),
5603 fNumberOfGridPoints);
5604 }
5605 xmin = fPntX[1][fNumberOfXConstPoints - 2];
5606 xrange = fPntX[1][1] - xmin;
5607
5608 for (i = 0; i < fNumberOfXConstPoints - 2; i++) {
5609 fUValues[1][i + 1] = (fPntX[1][i + 1] - xmin) / xrange;
5610 }
5611
5612 if (!Approx
5613 (&fPntY[1][1], &fUValues[1][1], fNumberOfXConstPoints - 2, fNumberOfXConstGridPoints, chn->fTempData))
5614 return true;
5615
5616 // error statistics
5617 if (fShowStatistics) {
5618 for (i = 0; i < fNumberOfPoints; i++) {
5619 uu = (fPntX[0][i] - xmin) / xrange;
5620 yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
5621 yr = fPntY[0][i];
5622 fStatisticsApprox[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
5623 }
5624 }
5625 // Add min and max point
5626 chn->fLimitGroup[fCurrentFitBin] = 0;
5627 while (xmin - kBSplineXMinOffset > data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin]) {
5628 chn->fLimitGroup[fCurrentFitBin]++;
5629 }
5630 if (data->fNumberOfLimitGroups <= chn->fLimitGroup[fCurrentFitBin])
5631 data->fNumberOfLimitGroups = chn->fLimitGroup[fCurrentFitBin] + 1;
5632 xminExt = data->fMin + kBSplineXMinOffset * chn->fLimitGroup[fCurrentFitBin];
5633 xrangeExt = data->fMax - xminExt;
5634
5635 fPntX[1][0] = data->fMax;
5636 uu = (fPntX[1][0] - xmin) / xrange;
5637 fPntY[1][0] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
5638
5639 fPntX[1][fNumberOfXConstPoints - 1] = xminExt;
5640 uu = (fPntX[1][fNumberOfXConstPoints - 1] - xmin) / xrange;
5641 fPntY[1][fNumberOfXConstPoints - 1] = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
5642
5643 for (i = 0; i < fNumberOfXConstPoints; i++) {
5644 fUValues[1][i] = (fPntX[1][i] - xminExt) / xrangeExt;
5645 }
5646
5647 if (!Approx(fPntY[1], fUValues[1], fNumberOfXConstPoints, fNumberOfXConstGridPoints, chn->fTempData))
5648 return true;
5649
5650 // error statistics
5651 if (fShowStatistics) {
5652 for (i = 0; i < fNumberOfPoints; i++) {
5653 uu = (fPntX[0][i] - xminExt) / xrangeExt;
5654 yc = GetValue(chn->fTempData, uu, fNumberOfXConstGridPoints);
5655 yr = fPntY[0][i];
5656 fStatisticsApproxExt[i][fCurrentFitBin + fCurrentFitChannel * kNumberOfBins] = yc - yr;
5657 }
5658 }
5659 for (i = 0; i < fNumberOfXConstGridPoints; i++) {
5660 chn->fData[fCurrentFitBin][i] = static_cast < short >(chn->fTempData[i] / fPrecision);
5661 }
5662
5663 // write end of file
5664 fCurrentFitBin++;
5665 if (fCurrentFitBin == kNumberOfBins) {
5666 fCurrentFitChannel++;
5667 fCurrentFitBin = 0;
5668 }
5669 if (fCurrentFitChannel == kNumberOfCalibChannelsV3) {
5670 if (fShowStatistics) {
5671 for (i = 0; i < fNumberOfPoints; i++) {
5672 average = 0;
5673 averageError = 0;
5674 averageExt = 0;
5675 averageErrorExt = 0;
5676 for (j = 0; j < kNumberOfCalibChannelsV3 * kNumberOfBins; j++) {
5677 average += fStatisticsApprox[i][j];
5678 averageError += fStatisticsApprox[i][j] * fStatisticsApprox[i][j];
5679 averageExt += fStatisticsApproxExt[i][j];
5680 averageErrorExt += fStatisticsApproxExt[i][j] * fStatisticsApproxExt[i][j];
5681 }
5682 average /= kNumberOfCalibChannelsV3 * kNumberOfBins;
5683 averageError =
5684 sqrt((averageError -
5685 average * average / kNumberOfCalibChannelsV3 * kNumberOfBins) /
5686 (kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
5687 averageExt /= kNumberOfCalibChannelsV3 * kNumberOfBins;
5688 averageErrorExt =
5689 sqrt((averageErrorExt -
5690 averageExt * averageExt / kNumberOfCalibChannelsV3 * kNumberOfBins) /
5691 (kNumberOfCalibChannelsV3 * kNumberOfBins - 1));
5692 printf("Error at %3.1f V : % 2.3f +- % 2.3f ; % 2.3f +- % 2.3f\n", fPntY[0][i], average,
5693 averageError, averageExt, averageErrorExt);
5694 }
5695 }
5696 fFitted = true;
5697 fOffset = false;
5698 fCalibrationData[chipNumber]->fRead = true;
5699 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
5700 data->PreCalculateBSpline();
5701 return true;
5702 }
5703 return false;
5704}
5705
5706/*------------------------------------------------------------------*/
5707
5708bool ResponseCalibration::FitCalibrationPointsV4(int chipNumber)
5709{
5710 if (!fRecorded || fFitted)
5711 return true;
5712 int i;
5713 double par[2];
5714 static int error;
5715
5716 CalibrationData *data = fCalibrationData[chipNumber];
5717 CalibrationData::CalibrationDataChannel * chn = data->fChannel[fCurrentFitChannel];
5718
5719 if (fCurrentFitBin == 0 && fCurrentFitChannel == 0) {
5720 error = 0;
5721 for (i = 0; i < fNumberOfPoints; i++)
5722 fWWFit[i] = 1;
5723 }
5724
5725 for (i = 0; i < fNumberOfPoints; i++) {
5726 fXXFit[i] = 1.0 * i / (static_cast < double >(fNumberOfPoints) - 1) +0.1;
5727 fYYFit[i] = fResponseX[fCurrentFitChannel][fCurrentFitBin][i];
5728 if (fCurrentFitBin == 10 && fCurrentFitChannel == 1) {
5729 fXXSave[i] = fXXFit[i];
5730 fYYSave[i] = fYYFit[i];
5731 }
5732 }
5733
5734 // DRSBoard::LinearRegression(fXXFit, fYYFit, fNumberOfPoints, &par[1], &par[0]);
5735 // exclude first two points (sometimes are on limit of FADC)
5736 DRSBoard::LinearRegression(fXXFit + 2, fYYFit + 2, fNumberOfPoints - 2, &par[1], &par[0]);
5737
5738 chn->fOffset[fCurrentFitBin] = static_cast < unsigned short >(par[0] + 0.5);
5739 chn->fGain[fCurrentFitBin] = static_cast < unsigned short >(par[1] + 0.5);
5740
5741 // Remember min/max of gain
5742 if (fCurrentFitBin == 0 && fCurrentFitChannel == 0)
5743 fGainMin = fGainMax = chn->fGain[0];
5744 if (chn->fGain[fCurrentFitBin] < fGainMin)
5745 fGainMin = chn->fGain[fCurrentFitBin];
5746 if (chn->fGain[fCurrentFitBin] > fGainMax)
5747 fGainMax = chn->fGain[fCurrentFitBin];
5748
5749 // abort if outside normal region
5750 if (chn->fGain[fCurrentFitBin] / 4096.0 < 0.8 || chn->fGain[fCurrentFitBin] / 4096.0 > 1) {
5751 error++;
5752
5753 if (error < 20)
5754 printf("Gain=%1.3lf for bin %d on channel %d on chip %d outside valid region\n",
5755 chn->fGain[fCurrentFitBin] / 4096.0, fCurrentFitBin, fCurrentFitChannel, chipNumber);
5756 }
5757
5758 if (fCurrentFitChannel == 1 && fCurrentFitBin == 10) {
5759 for (i = 0; i < fNumberOfPoints; i++) {
5760 fXXSave[i] = fXXFit[i];
5761 fYYSave[i] = (fYYFit[i] - chn->fOffset[10]) / chn->fGain[10] - fXXFit[i];
5762 }
5763 }
5764
5765 fCurrentFitBin++;
5766 if (fCurrentFitBin == kNumberOfBins) {
5767 fCurrentFitChannel++;
5768 fCurrentFitBin = 0;
5769 }
5770 if (fCurrentFitChannel == kNumberOfCalibChannelsV4) {
5771
5772 if (fBoard->Debug()) {
5773 printf("Gain min=%1.3lf max=%1.3lf\n", fGainMin / 4096.0, fGainMax / 4096.0);
5774 fflush(stdout);
5775 }
5776 // allow up to three bad bins
5777 if (error > 3) {
5778 printf("Aborting calibration!\n");
5779 return true;
5780 }
5781
5782 fFitted = true;
5783 fOffset = false;
5784 fCalibrationData[chipNumber]->fRead = true;
5785 fCalibrationData[chipNumber]->fHasOffsetCalibration = false;
5786 return true;
5787 }
5788
5789 return false;
5790}
5791
5792unsigned int millitime()
5793{
5794#ifdef _MSC_VER
5795
5796 return (int) GetTickCount();
5797
5798#else
5799 struct timeval tv;
5800
5801 gettimeofday(&tv, NULL);
5802
5803 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
5804#endif
5805 return 0;
5806}
5807
5808/*------------------------------------------------------------------*/
5809
5810bool ResponseCalibration::OffsetCalibration(int chipNumber)
5811{
5812 if (!fFitted || fOffset)
5813 return true;
5814 if (fBoard->GetDRSType() == 3)
5815 return OffsetCalibrationV4(chipNumber);
5816 else
5817 return OffsetCalibrationV3(chipNumber);
5818}
5819
5820/*------------------------------------------------------------------*/
5821
5822bool ResponseCalibration::OffsetCalibrationV3(int chipNumber)
5823{
5824 int k, ii, j;
5825 int t1, t2;
5826 float mean, error;
5827 CalibrationData *data = fCalibrationData[chipNumber];
5828 CalibrationData::CalibrationDataChannel * chn;
5829
5830 if (fCurrentSample == 0) {
5831 data->fHasOffsetCalibration = false;
5832 fBoard->SetCalibVoltage(0.0);
5833 fBoard->EnableAcal(0, 0.0);
5834 }
5835 // Loop Over Number Of Samples For Statistics
5836 t1 = millitime();
5837 fBoard->SoftTrigger();
5838 while (fBoard->IsBusy()) {
5839 }
5840 fBoard->TransferWaves();
5841 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5842 fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
5843 fBoard->CalibrateWaveform(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample],
5844 fWaveFormOffset[ii][fCurrentSample], true, false, false, 0, true);
5845 }
5846 fBoard->StartDomino();
5847 fBoard->IsBusy();
5848 fBoard->IsBusy();
5849 fBoard->IsBusy();
5850 t2 = millitime();
5851 while (t2 - t1 < (1000 / fTriggerFrequency)) {
5852 t2 = millitime();
5853 }
5854 fCurrentSample++;
5855
5856 if (fCurrentSample == fNumberOfSamples) {
5857 // Average Sample Points
5858 float *sample = new float[fNumberOfSamples];
5859 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5860 chn = data->fChannel[ii];
5861 for (k = 0; k < kNumberOfBins; k++) {
5862 for (j = 0; j < fNumberOfSamples; j++)
5863 sample[j] = static_cast < float >(fWaveFormOffset[ii][j][k]);
5864 Average(1, sample, fNumberOfSamples, mean, error, 2);
5865 chn->fOffset[k] = static_cast < short >(mean);
5866 for (j = 0; j < fNumberOfSamples; j++)
5867 sample[j] = fWaveFormOffsetADC[ii][j][k];
5868 Average(1, sample, fNumberOfSamples, mean, error, 2);
5869 chn->fOffsetADC[k] = static_cast < unsigned short >(mean);
5870 }
5871 }
5872 fOffset = true;
5873 fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
5874 delete sample;
5875 return true;
5876 }
5877
5878 return false;
5879}
5880
5881/*------------------------------------------------------------------*/
5882
5883bool ResponseCalibration::OffsetCalibrationV4(int chipNumber)
5884{
5885 int k, ii, j;
5886 float mean, error;
5887 CalibrationData *data = fCalibrationData[chipNumber];
5888 CalibrationData::CalibrationDataChannel * chn;
5889
5890 /* switch DRS to input, hope that no real signal occurs */
5891 if (fCurrentSample == 0) {
5892 data->fHasOffsetCalibration = false;
5893 fBoard->SetCalibVoltage(0.0);
5894 fBoard->EnableAcal(0, 0.0);
5895 /* one dummy trigger for unknown reasons */
5896 fBoard->SoftTrigger();
5897 while (fBoard->IsBusy());
5898 fBoard->StartDomino();
5899 Sleep(50);
5900 }
5901 // Loop Over Number Of Samples For Statistics
5902 fBoard->SoftTrigger();
5903 while (fBoard->IsBusy());
5904 fBoard->TransferWaves();
5905 for (ii = 0; ii < kNumberOfCalibChannelsV4; ii++)
5906 fBoard->GetRawWave(chipNumber, ii, fWaveFormOffsetADC[ii][fCurrentSample]);
5907
5908 fBoard->StartDomino();
5909 Sleep(50);
5910 fCurrentSample++;
5911
5912 if (fBoard->Debug()) {
5913 printf("%02d\r", fNumberOfSamples - fCurrentSample);
5914 fflush(stdout);
5915 }
5916
5917 if (fCurrentSample == fNumberOfSamples) {
5918 // Average Sample Points
5919 float *sample = new float[fNumberOfSamples];
5920 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5921 chn = data->fChannel[ii];
5922 for (k = 0; k < kNumberOfBins; k++) {
5923 for (j = 0; j < fNumberOfSamples; j++)
5924 sample[j] = static_cast < float >(fWaveFormOffsetADC[ii][j][k]);
5925 Average(1, sample, fNumberOfSamples, mean, error, 2);
5926 chn->fOffset[k] = static_cast < unsigned short >(mean);
5927 }
5928 }
5929 fOffset = true;
5930 fCalibrationData[chipNumber]->fHasOffsetCalibration = true;
5931 delete sample;
5932 return true;
5933 }
5934
5935 return false;
5936}
5937
5938/*------------------------------------------------------------------*/
5939
5940void ResponseCalibration::InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
5941 int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
5942 int numberOfXConstGridPoints, double triggerFrequency,
5943 int showStatistics)
5944{
5945 int ii, j, i;
5946 fInitialized = true;
5947 fNumberOfPointsLowVolt = numberOfPointsLowVolt;
5948 fNumberOfPoints = numberOfPoints;
5949 fNumberOfMode2Bins = numberOfMode2Bins;
5950 fNumberOfSamples = numberOfSamples;
5951 fNumberOfGridPoints = numberOfGridPoints;
5952 fNumberOfXConstPoints = numberOfXConstPoints;
5953 fNumberOfXConstGridPoints = numberOfXConstGridPoints;
5954 fTriggerFrequency = triggerFrequency;
5955 fShowStatistics = showStatistics;
5956 fCurrentPoint = 0;
5957 fCurrentSample = 0;
5958 fCurrentFitChannel = 0;
5959 fCurrentFitBin = 0;
5960 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5961 for (j = 0; j < kNumberOfBins; j++) {
5962 fResponseX[ii][j] = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
5963 }
5964 }
5965 fResponseY = new float[fNumberOfPoints + fNumberOfPointsLowVolt];
5966 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
5967 fWaveFormMode3[ii] = new unsigned short *[fNumberOfSamples];
5968 fWaveFormMode2[ii] = new unsigned short *[fNumberOfSamples];
5969 fWaveFormOffset[ii] = new short *[fNumberOfSamples];
5970 fWaveFormOffsetADC[ii] = new unsigned short *[fNumberOfSamples];
5971 for (i = 0; i < fNumberOfSamples; i++) {
5972 fWaveFormMode3[ii][i] = new unsigned short[kNumberOfBins];
5973 fWaveFormMode2[ii][i] = new unsigned short[kNumberOfBins];
5974 fWaveFormOffset[ii][i] = new short[kNumberOfBins];
5975 fWaveFormOffsetADC[ii][i] = new unsigned short[kNumberOfBins];
5976 }
5977 }
5978 fSamples = new unsigned short[fNumberOfSamples];
5979 fSampleUsed = new int[fNumberOfSamples];
5980
5981 for (j = 0; j < kNumberOfBins; j++) {
5982 fRes[j] = new float[fNumberOfGridPoints];
5983 fResX[j] = new float[fNumberOfGridPoints];
5984 }
5985 for (i = 0; i < 2; i++) {
5986 fPntX[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
5987 fPntY[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
5988 fUValues[i] = new float[fNumberOfPoints * (1 - i) + fNumberOfXConstPoints * i];
5989 }
5990 fXXFit = new double[fNumberOfPoints];
5991 fYYFit = new double[fNumberOfPoints];
5992 fWWFit = new double[fNumberOfPoints];
5993 fYYFitRes = new double[fNumberOfPoints];
5994 fYYSave = new double[fNumberOfPoints];
5995 fXXSave = new double[fNumberOfPoints];
5996
5997 fStatisticsApprox = new float *[fNumberOfPoints];
5998 fStatisticsApproxExt = new float *[fNumberOfPoints];
5999 for (i = 0; i < fNumberOfPoints; i++) {
6000 fStatisticsApprox[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
6001 fStatisticsApproxExt[i] = new float[kNumberOfCalibChannelsV3 * kNumberOfBins];
6002 }
6003 for (i = 0; i < kNumberOfChipsMax; i++) {
6004 fCalibrationData[i] = new CalibrationData(numberOfXConstGridPoints);
6005 }
6006}
6007
6008/*------------------------------------------------------------------*/
6009
6010void ResponseCalibration::DeleteFields()
6011{
6012 if (!fInitialized)
6013 return;
6014 fInitialized = false;
6015 int ii, j, i;
6016 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
6017 for (j = 0; j < kNumberOfBins; j++) {
6018 delete fResponseX[ii][j];
6019 }
6020 }
6021 delete fResponseY;
6022 for (ii = 0; ii < kNumberOfCalibChannelsV3; ii++) {
6023 for (i = 0; i < fNumberOfSamples; i++) {
6024 if (fWaveFormMode3[ii] != NULL)
6025 delete fWaveFormMode3[ii][i];
6026 if (fWaveFormMode2[ii] != NULL)
6027 delete fWaveFormMode2[ii][i];
6028 if (fWaveFormOffset[ii] != NULL)
6029 delete fWaveFormOffset[ii][i];
6030 if (fWaveFormOffsetADC[ii] != NULL)
6031 delete fWaveFormOffsetADC[ii][i];
6032 }
6033 delete fWaveFormMode3[ii];
6034 delete fWaveFormMode2[ii];
6035 delete fWaveFormOffset[ii];
6036 delete fWaveFormOffsetADC[ii];
6037 }
6038 delete fSamples;
6039 delete fSampleUsed;
6040
6041 for (j = 0; j < kNumberOfBins; j++) {
6042 delete fRes[j];
6043 delete fResX[j];
6044 }
6045 for (i = 0; i < 2; i++) {
6046 delete fPntX[i];
6047 delete fPntY[i];
6048 delete fUValues[i];
6049 }
6050 delete fXXFit;
6051 delete fYYFit;
6052 delete fWWFit;
6053 delete fYYFitRes;
6054 delete fYYSave;
6055 delete fXXSave;
6056
6057 for (i = 0; i < fNumberOfPoints; i++) {
6058 delete fStatisticsApprox[i];
6059 delete fStatisticsApproxExt[i];
6060 }
6061 delete fStatisticsApprox;
6062 delete fStatisticsApproxExt;
6063 for (i = 0; i < kNumberOfChipsMax; i++)
6064 delete fCalibrationData[i];
6065}
6066
6067/*------------------------------------------------------------------*/
6068
6069double ResponseCalibration::GetTemperature(unsigned int chipIndex)
6070{
6071 if (fCalibrationData[chipIndex] == NULL)
6072 return 0;
6073 if (!fCalibrationData[chipIndex]->fRead)
6074 return 0;
6075 return (fCalibrationData[chipIndex]->fStartTemperature + fCalibrationData[chipIndex]->fEndTemperature) / 2;
6076}
6077
6078/*------------------------------------------------------------------*/
6079
6080bool ResponseCalibration::Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
6081 short *uWaveform, int triggerCell, float threshold, bool offsetCalib)
6082{
6083 int i;
6084 unsigned int NumberOfCalibChannels;
6085 int hasOffset;
6086 bool aboveThreshold;
6087 float wave, v;
6088 int j, irot;
6089
6090 CalibrationData *data = fCalibrationData[chipIndex];
6091 CalibrationData::CalibrationDataChannel * chn;
6092
6093 if (fBoard->GetDRSType() == 3)
6094 NumberOfCalibChannels = kNumberOfCalibChannelsV4;
6095 else
6096 NumberOfCalibChannels = kNumberOfCalibChannelsV3;
6097
6098 if (channel >= NumberOfCalibChannels || data == NULL) {
6099 for (i = 0; i < kNumberOfBins; i++) {
6100 irot = i;
6101 if (triggerCell > -1)
6102 irot = (triggerCell + i) % kNumberOfBins;
6103
6104 uWaveform[i] = adcWaveform[irot];
6105 }
6106 return true;
6107 }
6108 if (!data->fRead) {
6109 for (i = 0; i < kNumberOfBins; i++) {
6110 uWaveform[i] = adcWaveform[i];
6111 }
6112 return true;
6113 }
6114
6115 chn = data->fChannel[channel];
6116
6117 hasOffset = data->fHasOffsetCalibration;
6118 aboveThreshold = (threshold == 0); // if threshold equal zero, always return true
6119
6120 short offset;
6121
6122 // Calibrate
6123 for (i = 0; i < kNumberOfBins; i++) {
6124 if (fBoard->GetDRSType() != 3) {
6125 irot = i;
6126 if (triggerCell > -1)
6127 irot = (triggerCell + i) % kNumberOfBins;
6128 offset = offsetCalib ? chn->fOffset[irot] : 0;
6129 if (adcWaveform[irot] > chn->fLookUpOffset[irot]) {
6130 uWaveform[i] =
6131 ((chn->fLookUp[irot][0] - chn->fLookUp[irot][1]) * (adcWaveform[irot] -
6132 chn->fLookUpOffset[irot]) +
6133 chn->fLookUp[irot][0]);
6134 } else if (adcWaveform[irot] <= chn->fLookUpOffset[irot]
6135 && adcWaveform[irot] > chn->fLookUpOffset[irot] - chn->fNumberOfLookUpPoints[irot]) {
6136 uWaveform[i] = chn->fLookUp[irot][chn->fLookUpOffset[irot] - adcWaveform[irot]];
6137 } else {
6138 wave = 0;
6139 for (j = 0; j < kBSplineOrder; j++) {
6140 wave +=
6141 chn->fData[irot][data->fBSplineOffsetLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]] + j]
6142 * data->fBSplineLookUp[adcWaveform[irot]][chn->fLimitGroup[irot]][j];
6143 }
6144 uWaveform[i] = static_cast < short >(wave);
6145 }
6146 // Offset Calibration
6147 if (hasOffset)
6148 uWaveform[i] -= offset;
6149 } else {
6150 irot = i;
6151 if (triggerCell > -1)
6152 irot = (triggerCell + i) % kNumberOfBins;
6153#if 0 /* not enabled yet for DRS3 */
6154 offset = offsetCalib ? chn->fOffset[irot] : 0;
6155#else
6156 offset = chn->fOffset[irot];
6157#endif
6158 v = static_cast < float >(adcWaveform[irot] - offset) / chn->fGain[irot];
6159 uWaveform[i] = static_cast < short >(v * 1000 / GetPrecision() + 0.5);
6160 }
6161
6162 // Check for Threshold
6163 if (!aboveThreshold) {
6164 if (uWaveform[i] >= threshold)
6165 aboveThreshold = true;
6166 }
6167 }
6168 return aboveThreshold;
6169}
6170
6171/*------------------------------------------------------------------*/
6172
6173bool ResponseCalibration::SubtractADCOffset(unsigned int chipIndex, unsigned int channel,
6174 unsigned short *adcWaveform,
6175 unsigned short *adcCalibratedWaveform,
6176 unsigned short newBaseLevel)
6177{
6178 int i;
6179 unsigned int NumberOfCalibChannels;
6180 CalibrationData *data = fCalibrationData[chipIndex];
6181 CalibrationData::CalibrationDataChannel * chn;
6182
6183 if (fBoard->GetDRSType() == 3)
6184 NumberOfCalibChannels = kNumberOfCalibChannelsV4;
6185 else
6186 NumberOfCalibChannels = kNumberOfCalibChannelsV3;
6187
6188 if (channel >= NumberOfCalibChannels || data == NULL)
6189 return false;
6190 if (!data->fRead || !data->fHasOffsetCalibration)
6191 return false;
6192
6193 chn = data->fChannel[channel];
6194 for (i = 0; i < kNumberOfBins; i++)
6195 adcCalibratedWaveform[i] = adcWaveform[i] - chn->fOffsetADC[i] + newBaseLevel;
6196 return true;
6197}
6198
6199
6200/*------------------------------------------------------------------*/
6201
6202bool ResponseCalibration::ReadCalibration(unsigned int chipIndex)
6203{
6204 if (fBoard->GetDRSType() == 3) return ReadCalibrationV4(chipIndex);
6205 else return ReadCalibrationV3(chipIndex);
6206}
6207
6208/*------------------------------------------------------------------*/
6209
6210bool ResponseCalibration::ReadCalibrationV3(unsigned int chipIndex)
6211{
6212 int k, l, m, num;
6213 unsigned char ng;
6214 short tempShort;
6215 char fileName[2000];
6216 FILE *fileHandle;
6217 char calibDir[1000];
6218
6219 // Read Response Calibration
6220 delete fCalibrationData[chipIndex];
6221 fCalibrationData[chipIndex] = NULL;
6222
6223 fBoard->GetCalibrationDirectory(calibDir);
6224 sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
6225 fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
6226 static_cast < int >(fBoard->GetFrequency() * 1000));
6227
6228 fileHandle = fopen(fileName, "rb");
6229 if (fileHandle == NULL) {
6230 printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
6231 printf("%s\n", fileName);
6232 return false;
6233 }
6234 // Number Of Grid Points
6235 num = fread(&ng, 1, 1, fileHandle);
6236 if (num != 1) {
6237 printf("Error while reading response calibration file '%s'\n", fileName);
6238 printf(" at 'NumberOfGridPoints'.\n");
6239 return false;
6240 }
6241
6242 fCalibrationData[chipIndex] = new CalibrationData(ng);
6243 CalibrationData *data = fCalibrationData[chipIndex];
6244 CalibrationData::CalibrationDataChannel * chn;
6245 data->fRead = true;
6246 data->fHasOffsetCalibration = 1;
6247 data->DeletePreCalculatedBSpline();
6248 fCalibrationValid[chipIndex] = true;
6249
6250 // Start Temperature
6251 num = fread(&tempShort, 2, 1, fileHandle);
6252 if (num != 1) {
6253 printf("Error while reading response calibration file '%s'\n", fileName);
6254 printf(" at 'StartTemperature'.\n");
6255 return false;
6256 }
6257 data->fStartTemperature = static_cast < float >(tempShort) / 10;
6258 // End Temperature
6259 num = fread(&tempShort, 2, 1, fileHandle);
6260 if (num != 1) {
6261 printf("Error while reading response calibration file '%s'\n", fileName);
6262 printf(" at 'EndTemperature'.\n");
6263 return false;
6264 }
6265 data->fEndTemperature = static_cast < float >(tempShort) / 10;
6266 if (fBoard->GetDRSType() != 3) {
6267 // Min
6268 num = fread(&data->fMin, 4, 1, fileHandle);
6269 if (num != 1) {
6270 printf("Error while reading response calibration file '%s'\n", fileName);
6271 printf(" at 'Min'.\n");
6272 return false;
6273 }
6274 // Max
6275 num = fread(&data->fMax, 4, 1, fileHandle);
6276 if (num != 1) {
6277 printf("Error while reading response calibration file '%s'\n", fileName);
6278 printf(" at 'Max'.\n");
6279 return false;
6280 }
6281 // Number Of Limit Groups
6282 num = fread(&data->fNumberOfLimitGroups, 1, 1, fileHandle);
6283 if (num != 1) {
6284 printf("Error while reading response calibration file '%s'\n", fileName);
6285 printf(" at 'NumberOfLimitGroups'.\n");
6286 return false;
6287 }
6288 }
6289 // read channel
6290 for (k = 0; k < kNumberOfCalibChannelsV3; k++) {
6291 chn = data->fChannel[k];
6292 for (l = 0; l < kNumberOfBins; l++) {
6293 if (fBoard->GetDRSType() != 3) {
6294 // Range Group
6295 num = fread(&chn->fLimitGroup[l], 1, 1, fileHandle);
6296 if (num != 1) {
6297 printf("Error while reading response calibration file '%s'\n", fileName);
6298 printf(" at 'RangeGroup' of channel %d bin %d.\n", k, l);
6299 return false;
6300 }
6301 // Look Up Offset
6302 num = fread(&chn->fLookUpOffset[l], 2, 1, fileHandle);
6303 if (num != 1) {
6304 printf("Error while reading response calibration file '%s'\n", fileName);
6305 printf(" at 'LookUpOffset' of channel %d bin %d.\n", k, l);
6306 return false;
6307 }
6308 // Number Of Look Up Points
6309 num = fread(&chn->fNumberOfLookUpPoints[l], 1, 1, fileHandle);
6310 if (num != 1) {
6311 printf("Error while reading response calibration file '%s'\n", fileName);
6312 printf(" at 'NumberOfLookUpPoints' of channel %d bin %d.\n", k, l);
6313 return false;
6314 }
6315 // Look Up Points
6316 delete chn->fLookUp[l];
6317 chn->fLookUp[l] = new unsigned char[chn->fNumberOfLookUpPoints[l]];
6318 for (m = 0; m < chn->fNumberOfLookUpPoints[l]; m++) {
6319 num = fread(&chn->fLookUp[l][m], 1, 1, fileHandle);
6320 if (num != 1) {
6321 printf("Error while reading response calibration file '%s'\n", fileName);
6322 printf(" at 'LookUp %d' of channel %d bin %d.\n", m, k, l);
6323 return false;
6324 }
6325 }
6326 // Points
6327 for (m = 0; m < data->fNumberOfGridPoints; m++) {
6328 num = fread(&chn->fData[l][m], 2, 1, fileHandle);
6329 if (num != 1) {
6330 printf("Error while reading response calibration file '%s'\n", fileName);
6331 printf(" at 'Point %d' of channel %d bin %d.\n", m, k, l);
6332 return false;
6333 }
6334 }
6335 // ADC Offset
6336 num = fread(&chn->fOffsetADC[l], 2, 1, fileHandle);
6337 if (num != 1) {
6338 printf("Error while reading response calibration file '%s'\n", fileName);
6339 printf(" at 'ADC Offset' of channel %d bin %d.\n", k, l);
6340 return false;
6341 }
6342 }
6343 // Offset
6344 num = fread(&chn->fOffset[l], 2, 1, fileHandle);
6345 if (num != 1) {
6346 printf("Error while reading response calibration file '%s'\n", fileName);
6347 printf(" at 'Offset' of channel %d bin %d.\n", k, l);
6348 return false;
6349 }
6350 if (fBoard->GetDRSType() == 3) {
6351 // Gain
6352 num = fread(&chn->fGain[l], 2, 1, fileHandle);
6353 if (num != 1) {
6354 printf("Error while reading response calibration file '%s'\n", fileName);
6355 printf(" at 'Gain' of channel %d bin %d.\n", k, l);
6356 return false;
6357 }
6358 }
6359 }
6360 }
6361 fclose(fileHandle);
6362
6363 if (fBoard->GetDRSType() != 3) {
6364 data->PreCalculateBSpline();
6365 }
6366
6367 return true;
6368}
6369
6370/*------------------------------------------------------------------*/
6371
6372bool ResponseCalibration::ReadCalibrationV4(unsigned int chipIndex)
6373{
6374 int k, l, num;
6375 char fileName[2000];
6376 FILE *fileHandle;
6377 char calibDir[1000];
6378
6379 // Read Response Calibration
6380
6381 fBoard->GetCalibrationDirectory(calibDir);
6382 sprintf(fileName, "%s/board%d/ResponseCalib_board%d_chip%d_%dMHz.bin", calibDir,
6383 fBoard->GetBoardSerialNumber(), fBoard->GetBoardSerialNumber(), chipIndex,
6384 static_cast < int >(fBoard->GetFrequency() * 1000));
6385
6386 fileHandle = fopen(fileName, "rb");
6387 if (fileHandle == NULL) {
6388 printf("Board %d --> Could not find response calibration file:\n", fBoard->GetBoardSerialNumber());
6389 printf("%s\n", fileName);
6390 return false;
6391 }
6392
6393 if (fInitialized)
6394 delete fCalibrationData[chipIndex];
6395 fCalibrationData[chipIndex] = new CalibrationData(1);
6396 CalibrationData *data = fCalibrationData[chipIndex];
6397 CalibrationData::CalibrationDataChannel * chn;
6398 data->fRead = true;
6399 data->fHasOffsetCalibration = 1;
6400 fCalibrationValid[chipIndex] = true;
6401 data->fStartTemperature = 0;
6402 data->fEndTemperature = 0;
6403
6404 // read channel
6405 for (k = 0; k < kNumberOfCalibChannelsV4; k++) {
6406 chn = data->fChannel[k];
6407 for (l = 0; l < kNumberOfBins; l++) {
6408 // Offset
6409 num = fread(&chn->fOffset[l], 2, 1, fileHandle);
6410 if (num != 1) {
6411 printf("Error while reading response calibration file '%s'\n", fileName);
6412 printf(" at 'Offset' of channel %d bin %d.\n", k, l);
6413 return false;
6414 }
6415 if (fBoard->GetDRSType() == 3) {
6416 // Gain
6417 num = fread(&chn->fGain[l], 2, 1, fileHandle);
6418 if (num != 1) {
6419 printf("Error while reading response calibration file '%s'\n", fileName);
6420 printf(" at 'Gain' of channel %d bin %d.\n", k, l);
6421 return false;
6422 }
6423 }
6424 }
6425 }
6426
6427 fclose(fileHandle);
6428 return true;
6429}
6430
6431/*------------------------------------------------------------------*/
6432
6433float ResponseCalibration::GetValue(float *coefficients, float u, int n)
6434{
6435 int j, ii;
6436 float bsplines[4];
6437 ii = CalibrationData::CalculateBSpline(n, u, bsplines);
6438
6439 float s = 0;
6440 for (j = 0; j < kBSplineOrder; j++) {
6441 s += coefficients[ii + j] * bsplines[j];
6442 }
6443 return s;
6444}
6445
6446/*------------------------------------------------------------------*/
6447
6448int ResponseCalibration::Approx(float *p, float *uu, int np, int nu, float *coef)
6449{
6450 int i, iu, j;
6451
6452 const int mbloc = 50;
6453 int ip = 0;
6454 int ir = 0;
6455 int mt = 0;
6456 int ileft, irow;
6457 float bu[kBSplineOrder];
6458 float *matrix[kBSplineOrder + 2];
6459 for (i = 0; i < kBSplineOrder + 2; i++)
6460 matrix[i] = new float[mbloc + nu + 1];
6461 for (iu = kBSplineOrder - 1; iu < nu; iu++) {
6462 for (i = 0; i < np; i++) {
6463 if (1 <= uu[i])
6464 ileft = nu - 1;
6465 else if (uu[i] < 0)
6466 ileft = kBSplineOrder - 2;
6467 else
6468 ileft = kBSplineOrder - 1 + static_cast < int >(uu[i] * (nu - kBSplineOrder + 1));
6469 if (ileft != iu)
6470 continue;
6471 irow = ir + mt;
6472 mt++;
6473 CalibrationData::CalculateBSpline(nu, uu[i], bu);
6474 for (j = 0; j < kBSplineOrder; j++) {
6475 matrix[j][irow] = bu[j];
6476 }
6477 matrix[kBSplineOrder][irow] = p[i];
6478 if (mt < mbloc)
6479 continue;
6480 LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
6481 mt = 0;
6482 }
6483 if (mt == 0)
6484 continue;
6485 LeastSquaresAccumulation(matrix, kBSplineOrder, &ip, &ir, mt, iu - kBSplineOrder + 1);
6486 mt = 0;
6487 }
6488 if (!LeastSquaresSolving(matrix, kBSplineOrder, ip, ir, coef, nu)) {
6489 for (i = 0; i < kBSplineOrder + 2; i++)
6490 delete matrix[i];
6491 return 0;
6492 }
6493
6494 for (i = 0; i < kBSplineOrder + 2; i++)
6495 delete matrix[i];
6496 return 1;
6497}
6498
6499/*------------------------------------------------------------------*/
6500
6501void ResponseCalibration::LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt)
6502{
6503 int i, j, l, mu, k, kh;
6504 float rho;
6505
6506 if (mt <= 0)
6507 return;
6508 if (jt != *ip) {
6509 if (jt > (*ir)) {
6510 for (i = 0; i < mt; i++) {
6511 for (j = 0; j < nb + 1; j++) {
6512 matrix[j][jt + mt - i] = matrix[j][(*ir) + mt - i];
6513 }
6514 }
6515 for (i = 0; i < jt - (*ir); i++) {
6516 for (j = 0; j < nb + 1; j++) {
6517 matrix[j][(*ir) + i] = 0;
6518 }
6519 }
6520 *ir = jt;
6521 }
6522 mu = min(nb - 1, (*ir) - (*ip) - 1);
6523 if (mu != 0) {
6524 for (l = 0; l < mu; l++) {
6525 k = min(l + 1, jt - (*ip));
6526 for (i = l + 1; i < nb; i++) {
6527 matrix[i - k][(*ip) + l + 1] = matrix[i][(*ip) + l + 1];
6528 }
6529 for (i = 0; i < k; i++) {
6530 matrix[nb - i - 1][(*ip) + l + 1] = 0;
6531 }
6532 }
6533 }
6534 *ip = jt;
6535 }
6536 kh = min(nb + 1, (*ir) + mt - (*ip));
6537
6538 for (i = 0; i < kh; i++) {
6539 Housholder(i, max(i + 1, (*ir) - (*ip)), (*ir) + mt - (*ip), matrix, i, (*ip), &rho, matrix, i + 1,
6540 (*ip), 1, nb - i);
6541 }
6542
6543 *ir = (*ip) + kh;
6544 if (kh < nb + 1)
6545 return;
6546 for (i = 0; i < nb; i++) {
6547 matrix[i][(*ir) - 1] = 0;
6548 }
6549}
6550
6551/*------------------------------------------------------------------*/
6552
6553int ResponseCalibration::LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n)
6554{
6555 int i, j, l, ii;
6556 float s, rsq;
6557 for (j = 0; j < n; j++) {
6558 x[j] = matrix[nb][j];
6559 }
6560 rsq = 0;
6561 if (n <= ir - 1) {
6562 for (j = n; j < ir; j++) {
6563 rsq += pow(matrix[nb][j], 2);
6564 }
6565 }
6566
6567 for (ii = 0; ii < n; ii++) {
6568 i = n - ii - 1;
6569 s = 0;
6570 l = max(0, i - ip);
6571 if (i != n - 1) {
6572 for (j = 1; j < min(n - i, nb); j++) {
6573 s += matrix[j + l][i] * x[i + j];
6574 }
6575 }
6576 if (matrix[l][i] == 0) {
6577 printf("Error in LeastSquaresSolving.\n");
6578 return 0;
6579 }
6580 x[i] = (x[i] - s) / matrix[l][i];
6581 }
6582 return 1;
6583}
6584
6585/*------------------------------------------------------------------*/
6586
6587void ResponseCalibration::Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up,
6588 float **c, int iC1, int iC2, int ice, int ncv)
6589{
6590 int i, j, incr;
6591 float tol = static_cast < float >(1e-20);
6592 float tolb = static_cast < float >(1e-24);
6593 float cl, clinv, sm, b;
6594
6595 if (lpivot < 0 || lpivot >= l1 || l1 > m - 1)
6596 return;
6597 cl = fabs(u[iU1][iU2 + lpivot]);
6598
6599 // Construct the transformation
6600 for (j = l1 - 1; j < m; j++)
6601 cl = max(fabsf(u[iU1][iU2 + j]), cl);
6602 if (cl < tol)
6603 return;
6604 clinv = 1 / cl;
6605 sm = pow(u[iU1][iU2 + lpivot] * clinv, 2);
6606 for (j = l1; j < m; j++) {
6607 sm = sm + pow(u[iU1][iU2 + j] * clinv, 2);
6608 }
6609 cl *= sqrt(sm);
6610 if (u[iU1][iU2 + lpivot] > 0)
6611 cl = -cl;
6612 *up = u[iU1][iU2 + lpivot] - cl;
6613 u[iU1][iU2 + lpivot] = cl;
6614
6615 if (ncv <= 0)
6616 return;
6617 b = (*up) * u[iU1][iU2 + lpivot];
6618 if (fabs(b) < tolb)
6619 return;
6620 if (b >= 0)
6621 return;
6622 b = 1 / b;
6623 incr = ice * (l1 - lpivot);
6624 for (j = 0; j < ncv; j++) {
6625 sm = c[iC1 + j][iC2 + lpivot] * (*up);
6626 for (i = l1; i < m; i++) {
6627 sm = sm + c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] * u[iU1][iU2 + i];
6628 }
6629 if (sm == 0)
6630 continue;
6631 sm *= b;
6632 c[iC1 + j][iC2 + lpivot] = c[iC1 + j][iC2 + lpivot] + sm * (*up);
6633 for (i = l1; i < m; i++) {
6634 c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] =
6635 c[iC1 + j][iC2 + lpivot + incr + (i - l1) * ice] + sm * u[iU1][iU2 + i];
6636 }
6637 }
6638}
6639
6640/*------------------------------------------------------------------*/
6641
6642int ResponseCalibration::MakeDir(const char *path)
6643{
6644 struct stat buf;
6645 if (stat(path, &buf)) {
6646#ifdef _MSC_VER
6647 return mkdir(path);
6648#else
6649 return mkdir(path, 0711);
6650#endif // R__UNIX
6651 }
6652 return 0;
6653}
6654
6655/*------------------------------------------------------------------*/
6656
6657ResponseCalibration::ResponseCalibration(DRSBoard *board)
6658: fBoard(board)
6659 , fPrecision(0.1) // mV
6660 , fInitialized(false)
6661 , fRecorded(false)
6662 , fFitted(false)
6663 , fOffset(false)
6664 , fNumberOfPointsLowVolt(0)
6665 , fNumberOfPoints(0)
6666 , fNumberOfMode2Bins(0)
6667 , fNumberOfSamples(0)
6668 , fNumberOfGridPoints(0)
6669 , fNumberOfXConstPoints(0)
6670 , fNumberOfXConstGridPoints(0)
6671 , fTriggerFrequency(0)
6672 , fShowStatistics(0)
6673 , fCalibFile(0)
6674 , fCurrentLowVoltPoint(0)
6675 , fCurrentPoint(0)
6676 , fCurrentSample(0)
6677 , fCurrentFitChannel(0)
6678 , fCurrentFitBin(0)
6679 , fResponseY(0)
6680 , fSamples(0)
6681 , fSampleUsed(0)
6682 , fXXFit(0)
6683 , fYYFit(0)
6684 , fWWFit(0)
6685 , fYYFitRes(0)
6686 , fYYSave(0)
6687 , fXXSave(0)
6688 , fStatisticsApprox(0)
6689 , fStatisticsApproxExt(0)
6690{
6691 int i;
6692 // Initializing the Calibration Class
6693 CalibrationData::fIntRevers[0] = 0;
6694 for (i = 1; i < 2 * kBSplineOrder - 2; i++) {
6695 CalibrationData::fIntRevers[i] = static_cast < float >(1.) / i;
6696 }
6697 for (i = 0; i < kNumberOfChipsMax; i++) {
6698 fCalibrationData[i] = NULL;
6699 }
6700 // Initializing the Calibration Creation
6701 fCalibrationValid[0] = false;
6702 fCalibrationValid[1] = false;
6703
6704 fBoard = board;
6705}
6706
6707/*------------------------------------------------------------------*/
6708
6709ResponseCalibration::~ResponseCalibration()
6710{
6711 // Delete the Calibration
6712 for (int i=0 ; i<kNumberOfChipsMax ; i++)
6713 delete fCalibrationData[i];
6714
6715 // Deleting the Calibration Creation
6716 DeleteFields();
6717}
6718
6719/*------------------------------------------------------------------*/
6720
6721float ResponseCalibration::CalibrationData::fIntRevers[2 * kBSplineOrder - 2];
6722ResponseCalibration::CalibrationData::CalibrationData(int numberOfGridPoints)
6723:fRead(false)
6724, fNumberOfGridPoints(numberOfGridPoints)
6725, fHasOffsetCalibration(0)
6726, fStartTemperature(0)
6727, fEndTemperature(0)
6728, fMin(0)
6729, fMax(0)
6730, fNumberOfLimitGroups(0)
6731{
6732 int i;
6733 for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
6734 fChannel[i] = new CalibrationDataChannel(numberOfGridPoints);
6735 }
6736 for (i = 0; i < kNumberOfADCBins; i++) {
6737 fBSplineOffsetLookUp[i] = NULL;
6738 fBSplineLookUp[i] = NULL;
6739 }
6740};
6741
6742/*------------------------------------------------------------------*/
6743
6744void ResponseCalibration::CalibrationData::PreCalculateBSpline()
6745{
6746 int i, j;
6747 float uu;
6748 float xmin, xrange;
6749 int nk = fNumberOfGridPoints - kBSplineOrder + 1;
6750 for (i = 0; i < kNumberOfADCBins; i++) {
6751 fBSplineLookUp[i] = new float *[fNumberOfLimitGroups];
6752 fBSplineOffsetLookUp[i] = new int[fNumberOfLimitGroups];
6753 for (j = 0; j < fNumberOfLimitGroups; j++) {
6754 fBSplineLookUp[i][j] = new float[kBSplineOrder];
6755 xmin = fMin + j * kBSplineXMinOffset;
6756 xrange = fMax - xmin;
6757 uu = (i - xmin) / xrange;
6758 if (i < xmin) {
6759 uu = 0;
6760 }
6761 if (i - xmin > xrange) {
6762 uu = 1;
6763 }
6764 fBSplineOffsetLookUp[i][j] = static_cast < int >(uu * nk);
6765 CalculateBSpline(fNumberOfGridPoints, uu, fBSplineLookUp[i][j]);
6766 }
6767 }
6768}
6769
6770/*------------------------------------------------------------------*/
6771
6772void ResponseCalibration::CalibrationData::DeletePreCalculatedBSpline()
6773{
6774 int i, j;
6775 for (i = 0; i < kNumberOfADCBins; i++) {
6776 if (fBSplineLookUp[i] != NULL) {
6777 for (j = 0; j < fNumberOfLimitGroups; j++)
6778 delete fBSplineLookUp[i][j];
6779 }
6780 delete fBSplineLookUp[i];
6781 delete fBSplineOffsetLookUp[i];
6782 }
6783}
6784
6785/*------------------------------------------------------------------*/
6786
6787ResponseCalibration::CalibrationData::~CalibrationData()
6788{
6789 int i, j;
6790 for (i = 0; i < kNumberOfCalibChannelsV3; i++) {
6791 delete fChannel[i];
6792 }
6793 for (i = 0; i < kNumberOfADCBins; i++) {
6794 if (fBSplineLookUp[i] != NULL) {
6795 for (j = 0; j < fNumberOfLimitGroups; j++) {
6796 delete fBSplineLookUp[i][j];
6797 }
6798 }
6799 delete fBSplineLookUp[i];
6800 delete fBSplineOffsetLookUp[i];
6801 }
6802};
6803
6804/*------------------------------------------------------------------*/
6805
6806int ResponseCalibration::CalibrationData::CalculateBSpline(int nGrid, float value, float *bsplines)
6807{
6808 int minimum;
6809 int maximum;
6810 float xl;
6811
6812 int nk = nGrid - kBSplineOrder + 1;
6813 float vl = value * nk;
6814 int ivl = static_cast < int >(vl);
6815
6816 if (1 <= value) {
6817 xl = vl - nk + 1;
6818 minimum = 1 - nk;
6819 } else if (value < 0) {
6820 xl = vl;
6821 minimum = 0;
6822 } else {
6823 xl = vl - ivl;
6824 minimum = -ivl;
6825 }
6826 maximum = nk + minimum;
6827
6828// printf("xl = %f\n",xl);
6829 float vm, vmprev;
6830 int jl, ju;
6831 int nb = 0;
6832
6833 bsplines[0] = 1;
6834 for (int i = 0; i < kBSplineOrder - 1; i++) {
6835 vmprev = 0;
6836 for (int j = 0; j < nb + 1; j++) {
6837 jl = max(minimum, j - nb);
6838 ju = min(maximum, j + 1);
6839 vm = bsplines[j] * fIntRevers[ju - jl];
6840 bsplines[j] = vm * (ju - xl) + vmprev;
6841 vmprev = vm * (xl - jl);
6842 }
6843 nb++;
6844 bsplines[nb] = vmprev;
6845 }
6846 return -minimum;
6847}
6848
6849/*------------------------------------------------------------------*/
6850
6851void ResponseCalibration::Average(int method, float *points, int numberOfPoints, float &mean, float &error,
6852 float sigmaBoundary)
6853{
6854 // Methods :
6855 // 0 : Average
6856 // 1 : Average inside sigmaBoundary*sigma
6857 int i;
6858 float sum = 0;
6859 float sumSquare = 0;
6860
6861 if (method == 0 || method == 1) {
6862 for (i = 0; i < numberOfPoints; i++) {
6863 sum += points[i];
6864 sumSquare += points[i] * points[i];
6865 }
6866
6867 mean = sum / numberOfPoints;
6868 error = sqrt((sumSquare - sum * sum / numberOfPoints) / (numberOfPoints - 1));
6869 }
6870 if (method == 1) {
6871 int numberOfGoodPoints = numberOfPoints;
6872 bool found = true;
6873 bool *goodSample = new bool[numberOfGoodPoints];
6874 for (i = 0; i < numberOfGoodPoints; i++)
6875 goodSample[i] = true;
6876
6877 while (found) {
6878 found = false;
6879 for (i = 0; i < numberOfPoints; i++) {
6880 if (goodSample[i] && fabs(points[i] - mean) > sigmaBoundary * error) {
6881 found = true;
6882 goodSample[i] = false;
6883 numberOfGoodPoints--;
6884 sum -= points[i];
6885 sumSquare -= points[i] * points[i];
6886 mean = sum / numberOfGoodPoints;
6887 error = sqrt((sumSquare - sum * sum / numberOfGoodPoints) / (numberOfGoodPoints - 1));
6888 }
6889 }
6890 }
6891 delete goodSample;
6892 }
6893}
6894
6895
6896//**************************************************************************************************
6897//**
6898//** All functions special to the Concurrent Technologies single-board computer are collected here
6899//**
6900//**************************************************************************************************
6901
6902#ifdef CT_VME
6903
6904// Open VME connection
6905int DRS::OpenVME() {
6906
6907 if ((ErrorCode = VME_Open()) != VME_SUCCESS) {
6908 VME_ErrorString(ErrorCode,ErrorString);
6909 printf("VME_Open() %s\n",ErrorString);
6910 }
6911 return ErrorCode;
6912}
6913
6914// Do master mapping
6915int DRS::MasterMapVME(int *MMap) {
6916
6917 if (ErrorCode = VME_MasterMap(&MasterMap, MMap)) {
6918 VME_ErrorString(ErrorCode,ErrorString);
6919 printf("VME_MasterMap() %s\n",ErrorString);
6920 }
6921 return(ErrorCode);
6922}
6923
6924// Delete master mapping
6925int DRS::MasterUnMapVME(int MMap) {
6926
6927 if (ErrorCode = VME_MasterUnmap(MMap)) {
6928 VME_ErrorString(ErrorCode,ErrorString);
6929 printf("VME_MasterUnmap() %s\n",ErrorString);
6930 }
6931 return(ErrorCode);
6932}
6933
6934// Close VME connection
6935int DRS::CloseVME() {
6936
6937 if ((ErrorCode = VME_Close()) != VME_SUCCESS) {
6938 VME_ErrorString(ErrorCode,ErrorString);
6939 printf("VME_Close() %s\n",ErrorString);
6940 }
6941 return ErrorCode;
6942}
6943
6944// Open CMEM package
6945int DRS::OpenCMEM() {
6946
6947 if ((ErrorCode = CMEM_Open()) != CMEM_RCC_SUCCESS) {
6948 VME_ErrorString(ErrorCode,ErrorString);
6949 printf("CMEM_Open() %s\n",ErrorString);
6950 }
6951 return ErrorCode;
6952}
6953
6954// Close CMEM package
6955int DRS::CloseCMEM() {
6956
6957 if ((ErrorCode = CMEM_Close()) != CMEM_RCC_SUCCESS) {
6958 VME_ErrorString(ErrorCode,ErrorString);
6959 printf("CMEM_Close %s\n",ErrorString);
6960 }
6961 return ErrorCode;
6962}
6963
6964int DRSBoard::AllocateSegmentCMEM(unsigned int SegSize, int *CMEM_SegIdentifier) {
6965
6966 if ((ErrorCode = CMEM_SegmentAllocate(SegSize, "DMA_BUFFER", CMEM_SegIdentifier)) != CMEM_RCC_SUCCESS) {
6967 VME_ErrorString(ErrorCode,ErrorString);
6968 printf("CMEM_SegmentAllocate() %s\n",ErrorString);
6969 }
6970 return ErrorCode;
6971}
6972
6973
6974int DRSBoard::AssignPhysicalSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* PCIAddress) {
6975
6976 if ((ErrorCode = CMEM_SegmentPhysicalAddress(CMEM_SegIdentifier, PCIAddress)) != CMEM_RCC_SUCCESS) {
6977 VME_ErrorString(ErrorCode,ErrorString);
6978 printf("CMEM_SegmentPhysicalAddress() %s\n",ErrorString);
6979 }
6980 return ErrorCode;
6981}
6982
6983
6984int DRSBoard::AssignVirtualSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* VirtualAddress) {
6985
6986 if ((ErrorCode = CMEM_SegmentVirtualAddress(CMEM_SegIdentifier, VirtualAddress)) != CMEM_RCC_SUCCESS) {
6987 VME_ErrorString(ErrorCode,ErrorString);
6988 printf("CMEM_SegmentVirtualAddress() %s\n",ErrorString);
6989 }
6990 return ErrorCode;
6991}
6992
6993// Free memory segment
6994int DRSBoard::FreeSegmentCMEM(int CMEM_SegIdentifier) {
6995
6996 if ((ErrorCode = CMEM_SegmentFree(CMEM_SegIdentifier)) != CMEM_RCC_SUCCESS) {
6997 VME_ErrorString(ErrorCode,ErrorString);
6998 printf("CMEM_SegmentFree() %s\n",ErrorString);
6999 }
7000 return ErrorCode;
7001 }
7002
7003
7004#endif
Note: See TracBrowser for help on using the repository browser.