Subversion Repositories f9daq

Rev

Rev 197 | Details | Compare with Previous | Last modification | View Log | RSS feed

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