Subversion Repositories f9daq

Rev

Rev 195 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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. }
  7734.