DRS4 Forum
  DRS4 Discussion Forum  Not logged in ELOG logo
Entry  Tue Apr 28 11:44:07 2009, Stefan Ritt, Simple example application to read a DRS evaluation board drs_exam.cpp
    Reply  Wed Apr 29 07:57:33 2009, Stefan Ritt, Simple example application to read a DRS evaluation board DRS.cppDRS.h
    Reply  Mon Apr 5 17:57:41 2010, Heejong Kim, Simple example application to read a DRS evaluation board 
       Reply  Tue Apr 13 14:15:16 2010, Stefan Ritt, Simple example application to read a DRS evaluation board 
Message ID: 8     Entry time: Wed Apr 29 07:57:33 2009     In reply to: 7
Author: Stefan Ritt 
Subject: Simple example application to read a DRS evaluation board 

 

Stefan Ritt wrote:

Several people asked for s simple application to guide them in writing their own application to read out a DRS board. Such an application has been added in software revions 2.1.1 and is attached to this message. This example program drs_exam.cpp written in C++ does the following necessary steps to access a DRS board:

  • Crate a "DRS" object and scan all USB devices
  • Display found DRS boards
  • Initialize the first found board and set the sampling frequency to 5 GSPS
  • Enable internal trigger on channel #1 with 250 mV threshold
  • Start acquisition and wait for a trigger
  • Read two waveforms (both time and amplitude)
  • Repeat this 10 times

I know that we are still missing a good documentation for the DRS API, but I have not yet found the time to do that. I hope the example program is enough for most people to start writing own programs. For Windows users (MS Visual C++ 8.0) there is a drs.sln project file, and for linux users there is a Makefile which can be used to compile this example program.

 

 

One note: The program drs_exam.cpp published in the previous message needs the current version of the DRS library in DRS.cpp and DRS.h. They are contained in the software release 2.1.1 which has to be downloaded. For simplicity, I attached the two files to this message.

Attachment 1: DRS.cpp  163 kB  | Hide | Hide all
/********************************************************************

  Name:         DRS.cpp
  Created by:   Stefan Ritt, Matthias Schneebeli

  Contents:     Library functions for DRS mezzanine and USB boards

  $Id: DRS.cpp 13351 2009-04-28 11:12:54Z ritt@PSI.CH $

\********************************************************************/

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <algorithm>
#include <sys/stat.h>
#include "strlcpy.h"

#ifdef _MSC_VER
#pragma warning(disable:4996)
#   include <windows.h>
#   include <direct.h>
#else
#   include <unistd.h>
#   include <sys/time.h>
inline void Sleep(useconds_t x)
{
   usleep(x * 1000);
}
#endif

#ifdef _MSC_VER
#include <conio.h>
#define drs_kbhit() kbhit()
#else
#include <sys/ioctl.h>
int drs_kbhit()
{
   int n;

   ioctl(0, FIONREAD, &n);
   return (n > 0);
}
static inline int getch()
{
   return getchar();
}
#endif

#include <DRS.h>

#ifdef _MSC_VER
extern "C" {
#endif

#include <mxml.h>

#ifdef _MSC_VER
}
#endif

/*---- minimal FPGA firmvare version required for this library -----*/
const int REQUIRED_FIRMWARE_VERSION_DRS2 = 5268;
const int REQUIRED_FIRMWARE_VERSION_DRS3 = 6981;
const int REQUIRED_FIRMWARE_VERSION_DRS4 = 13191;

/*---- VME addresses -----------------------------------------------*/
#ifdef HAVE_VME
/* assuming following DIP Switch settings:

   SW1-1: 1 (off)       use geographical addressing (1=left, 21=right)
   SW1-2: 1 (off)       \
   SW1-3: 1 (off)        >  VME_WINSIZE = 8MB, subwindow = 1MB
   SW1-4: 0 (on)        /
   SW1-5: 0 (on)        reserverd
   SW1-6: 0 (on)        reserverd
   SW1-7: 0 (on)        reserverd
   SW1-8: 0 (on)       \
                        |
   SW2-1: 0 (on)        |
   SW2-2: 0 (on)        |
   SW2-3: 0 (on)        |
   SW2-4: 0 (on)        > VME_ADDR_OFFSET = 0
   SW2-5: 0 (on)        |
   SW2-6: 0 (on)        |
   SW2-7: 0 (on)        |
   SW2-8: 0 (on)       /

   which gives
     VME base address = SlotNo * VME_WINSIZE + VME_ADDR_OFFSET
                      = SlotNo * 0x80'0000
*/
#define GEVPC_BASE_ADDR           0x00000000
#define GEVPC_WINSIZE               0x800000
#define GEVPC_USER_FPGA   (GEVPC_WINSIZE*2/8)
#define PMC1_OFFSET                  0x00000
#define PMC2_OFFSET                  0x80000
#define PMC_CTRL_OFFSET              0x00000    /* all registers 32 bit */
#define PMC_STATUS_OFFSET            0x10000
#define PMC_FIFO_OFFSET              0x20000
#define PMC_RAM_OFFSET               0x40000
#endif                          // HAVE_VME
/*---- USB addresses -----------------------------------------------*/
#define USB_TIMEOUT                     1000    // one second
#ifdef HAVE_USB
#define USB_CTRL_OFFSET                 0x00    /* all registers 32 bit */
#define USB_STATUS_OFFSET               0x40
#define USB_RAM_OFFSET                  0x80
#define USB_CMD_IDENT                      0    // Query identification
#define USB_CMD_ADDR                       1    // Address cycle
#define USB_CMD_READ                       2    // "VME" read <addr><size>
#define USB_CMD_WRITE                      3    // "VME" write <addr><size>
#define USB_CMD_READ12                     4    // 12-bit read <LSB><MSB>
#define USB_CMD_WRITE12                    5    // 12-bit write <LSB><MSB>

#define USB2_CMD_READ                      1
#define USB2_CMD_WRITE                     2
#define USB2_CTRL_OFFSET             0x00000    /* all registers 32 bit */
#define USB2_STATUS_OFFSET           0x10000
#define USB2_FIFO_OFFSET             0x20000
#define USB2_RAM_OFFSET              0x40000
#endif                          // HAVE_USB

/*---- Register addresses ------------------------------------------*/

#ifndef T_CTRL
#define T_CTRL                             1
#define T_STATUS                           2
#define T_RAM                              3
#define T_FIFO                             4
#endif

#define REG_CTRL                     0x00000    /* 32 bit control reg */
#define REG_DAC_OFS                  0x00004
#define REG_DAC0                     0x00004
#define REG_DAC1                     0x00006
#define REG_DAC2                     0x00008
#define REG_DAC3                     0x0000A
#define REG_DAC4                     0x0000C
#define REG_DAC5                     0x0000E
#define REG_DAC6                     0x00010
#define REG_DAC7                     0x00012
#define REG_CHANNEL_CONFIG           0x00014    // low byte
#define REG_CONFIG                   0x00014    // high byte
#define REG_CHANNEL_SPAN             0x00016
#define REG_FREQ_SET_HI              0x00018    // DRS2
#define REG_FREQ_SET_LO              0x0001A    // DRS2
#define REG_TRG_DELAY                0x00018    // DRS4
#define REG_FREQ_SET                 0x0001A    // DRS4
#define REG_TRIG_DELAY               0x0001C
#define REG_LMK_MSB                  0x0001C    // DRS4 Mezz
#define REG_CALIB_TIMING             0x0001E    // DRS2
#define REG_EEPROM_PAGE              0x0001E    // DRS4
#define REG_LMK_LSB                  0x0001E    // DRS4 Mezz

#define REG_MAGIC                    0x00000
#define REG_BOARD_TYPE               0x00002
#define REG_STATUS                   0x00004
#define REG_RDAC_OFS                 0x0000E
#define REG_RDAC0                    0x00008
#define REG_STOP_CELL0               0x00008
#define REG_RDAC1                    0x0000A
#define REG_STOP_CELL1               0x0000A
#define REG_RDAC2                    0x0000C
#define REG_STOP_CELL2               0x0000C
#define REG_RDAC3                    0x0000E
#define REG_STOP_CELL3               0x0000E
#define REG_RDAC4                    0x00000
#define REG_RDAC5                    0x00002
#define REG_RDAC6                    0x00014
#define REG_RDAC7                    0x00016
#define REG_EVENTS_IN_FIFO           0x00018
#define REG_EVENT_COUNT              0x0001A
#define REG_FREQ1                    0x0001C
#define REG_FREQ2                    0x0001E
#define REG_TEMPERATURE              0x00020
#define REG_TRIGGER_BUS              0x00022
#define REG_SERIAL_BOARD             0x00024
#define REG_VERSION_FW               0x00026

/*------------------------------------------------------------------*/

using namespace std;

#ifdef HAVE_USB
#define USB2_BUFFER_SIZE (1024*1024+10)
unsigned char static *usb2_buffer = NULL;
#endif

/*------------------------------------------------------------------*/

DRS::DRS()
:  fNumberOfBoards(0)
#ifdef HAVE_VME
    , fVmeInterface(0)
#endif
{
#ifdef HAVE_USB
   MUSB_INTERFACE *usb_interface;
#endif

#if defined(HAVE_VME) || defined(HAVE_USB)
   int index = 0, i = 0;
#endif

   memset(fError, 0, sizeof(fError));

#ifdef HAVE_VME
   unsigned short type, fw, magic, serial, temperature;
   mvme_addr_t addr;

   if (mvme_open(&fVmeInterface, 0) == MVME_SUCCESS) {

      mvme_set_am(fVmeInterface, MVME_AM_A32);
      mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);

      /* check all VME slave slots */
      for (index = 2; index <= 21; index++) {

         /* check PMC1 */
         addr = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE;        // VME board base address
         addr += GEVPC_USER_FPGA;       // UsrFPGA base address
         addr += PMC1_OFFSET;   // PMC1 offset

         mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
         i = mvme_read(fVmeInterface, &magic, addr + PMC_STATUS_OFFSET + REG_MAGIC, 2);
         if (i == 2) {
            if (magic != 0xC0DE) {
               printf("Found old firmware, please upgrade immediately!\n");
               fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1);
               fNumberOfBoards++;
            } else {

               /* read board type */
               mvme_read(fVmeInterface, &type, addr + PMC_STATUS_OFFSET + REG_BOARD_TYPE, 2);
               type &= 0xFF;
               if (type == 2 || type == 3 || type == 4) {    // DRS2 or DRS3 or DRS4

                  /* read firmware number */
                  mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_VERSION_FW, 2);

                  /* read serial number */
                  mvme_read(fVmeInterface, &serial, addr + PMC_STATUS_OFFSET + REG_SERIAL_BOARD, 2);

                  /* read temperature register to see if CMC card is present */
                  mvme_read(fVmeInterface, &temperature, addr + PMC_STATUS_OFFSET + REG_TEMPERATURE, 2);

                  /* LED blinking */
#if 0
                  do {
                     data = 0x00040000;
                     mvme_write(fVmeInterface, addr + PMC_CTRL_OFFSET + REG_CTRL, &data, sizeof(data));
                     mvme_write(fVmeInterface, addr + PMC2_OFFSET + PMC_CTRL_OFFSET + REG_CTRL, &data,
                                sizeof(data));

                     Sleep(500);

                     data = 0x00000000;
                     mvme_write(fVmeInterface, addr + PMC_CTRL_OFFSET + REG_CTRL, &data, sizeof(data));
                     mvme_write(fVmeInterface, addr + PMC2_OFFSET + PMC_CTRL_OFFSET + REG_CTRL, data,
                                sizeof(data));

                     Sleep(500);

                  } while (1);
#endif

                  if (temperature == 0xFFFF) {
                     //printf("slot %d, fw %d, no CMC board in upper slot\n", index, fw);
                  } else {
                     //printf("slot %d, fw %d, CMC serial %d in upper slot\n", index, fw, serial);

                     fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1);
                     if (fBoard[fNumberOfBoards]->HasCorrectFirmware())
                        fNumberOfBoards++;
                     else
                        sprintf(fError, "Wrong firmware version: board has %d, required is %d\n",
                                fBoard[fNumberOfBoards]->GetFirmwareVersion(),
                                fBoard[fNumberOfBoards]->GetRequiredFirmwareVersion());
                  }
               }
            }
         }

         /* check PMC2 */
         addr = GEVPC_BASE_ADDR + index * GEVPC_WINSIZE;        // VME board base address
         addr += GEVPC_USER_FPGA;       // UsrFPGA base address
         addr += PMC2_OFFSET;   // PMC2 offset

         mvme_set_dmode(fVmeInterface, MVME_DMODE_D16);
         i = mvme_read(fVmeInterface, &fw, addr + PMC_STATUS_OFFSET + REG_MAGIC, 2);
         if (i == 2) {
            if (magic != 0xC0DE) {
               printf("Found old firmware, please upgrade immediately!\n");
               fBoard[fNumberOfBoards] = new DRSBoard(fVmeInterface, addr, (index - 2) << 1 | 1);
               fNumberOfBoards++;
            } else {
... 5173 more lines ...
Attachment 2: DRS.h  26 kB  | Hide | Hide all
/********************************************************************
  DRS.h, S.Ritt, M. Schneebeli - PSI

  $Id: DRS.h 13347 2009-04-28 08:24:05Z ritt@PSI.CH $

********************************************************************/
#ifndef DRS_H
#define DRS_H
#include <stdio.h>
#include <string.h>

#ifdef HAVE_LIBUSB
#   ifndef HAVE_USB
#      define HAVE_USB
#   endif
#endif

#ifdef HAVE_USB
#   include <musbstd.h>
#endif                          // HAVE_USB

#ifdef HAVE_VME
#   include <mvmestd.h>
#endif                          // HAVE_VME

/* disable "deprecated" warning */
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif

#ifndef NULL
#define NULL 0
#endif

/* transport mode */
#define TR_VME   1
#define TR_USB   2
#define TR_USB2  3

/* address types */
#define T_CTRL   1
#define T_STATUS 2
#define T_RAM    3
#define T_FIFO   4

/* control register bit definitions */
#define BIT_START_TRIG        (1<<0)    // write a "1" to start domino wave
#define BIT_REINIT_TRIG       (1<<1)    // write a "1" to stop & reset DRS
#define BIT_SOFT_TRIG         (1<<2)    // write a "1" to stop and read data to RAM
#define BIT_EEPROM_WRITE_TRIG (1<<3)    // write a "1" to write into serial EEPROM
#define BIT_EEPROM_READ_TRIG  (1<<4)    // write a "1" to read from serial EEPROM
#define BIT_AUTOSTART        (1<<16)
#define BIT_DMODE            (1<<17)    // (*DRS2*) 0: single shot, 1: circular
#define BIT_LED              (1<<18)    // 1=on, 0=blink during readout
#define BIT_TCAL_EN          (1<<19)    // switch on (1) / off (0) for 33 MHz calib signal
#define BIT_TCAL_SOURCE      (1<<20)
#define BIT_REFCLK_SOURCE    (1<<20)
#define BIT_FREQ_AUTO_ADJ    (1<<21)    // DRS2/3
#define BIT_TRANSP_MODE      (1<<21)    // DRS4
#define BIT_ENABLE_TRIGGER1  (1<<22)    // External LEMO/FP/TRBUS trigger
#define BIT_LONG_START_PULSE (1<<23)    // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz)
#define BIT_READOUT_MODE     (1<<23)    // (*DRS3*) 0:start from first bin, 1:start from domino stop
#define BIT_DELAYED_START    (1<<24)    // DRS2: start domino wave 400ns after soft trigger, used for waveform
                                        // generator startup
#define BIT_NEG_TRIGGER      (1<<24)    // DRS4: use high-to-low trigger if set
#define BIT_ACAL_EN          (1<<25)    // connect DRS to inputs (0) or to DAC6 (1)
#define BIT_TRIGGER_DELAYED  (1<<26)    // select delayed trigger from trigger bus
#define BIT_DACTIVE          (1<<27)    // keep domino wave running during readout
#define BIT_STANDBY_MODE     (1<<28)    // put chip in standby mode
#define BIT_TR_SOURCE1       (1<<29)    // trigger source selection bits
#define BIT_TR_SOURCE2       (1<<30)    // trigger source selection bits
#define BIT_ENABLE_TRIGGER2  (1<<31)    // analog threshold (internal) trigger

/* status register bit definitions */
#define BIT_RUNNING           (1<<0)    // one if domino wave running or readout in progress
#define BIT_NEW_FREQ1         (1<<1)    // one if new frequency measurement available
#define BIT_NEW_FREQ2         (1<<2)
#define BIT_PLL_LOCKED0       (1<<1)    // 1 if PLL has locked (DRS4 evaluation board only)
#define BIT_PLL_LOCKED1       (1<<2)    // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only)
#define BIT_PLL_LOCKED2       (1<<3)    // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only)
#define BIT_PLL_LOCKED3       (1<<4)    // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only)
#define BIT_EEPROM_BUSY       (1<<5)    // 1 if EEPROM operation in progress

/* configuration register bit definitions */
#define BIT_CONFIG_DMODE      (1<<8)    // 0: single shot, 1: circular
#define BIT_CONFIG_PLLEN      (1<<9)    // write a "1" to enable the internal PLL
#define BIT_CONFIG_WSRLOOP   (1<<10)    // write a "1" to connect WSROUT to WSRIN internally

enum DRSBoardConstants {
   kNumberOfChannelsV2          =   10,
   kNumberOfChannelsV4          =    9,
   kNumberOfCalibChannelsV3     =   10,
   kNumberOfCalibChannelsV4     =    9,
   kNumberOfBins                = 1024,
   kNumberOfChips               =    2,
   kFrequencyCacheSize          =   10,
   kBSplineOrder                =    4,
   kPreCaliculatedBSplines      = 1000,
   kPreCaliculatedBSplineGroups =    5,
   kNumberOfADCBins             = 4096,
   kBSplineXMinOffset           =   20,
   kMaxNumberOfClockCycles      =  100,
};

enum DRSErrorCodes {
   kSuccess                     =  0,
   kInvalidTriggerSignal        = -1,
   kWrongChannelOrChip          = -2,
   kInvalidTransport            = -3,
   kZeroSuppression             = -4,
   kWaveNotAvailable            = -5
};

/*---- callback class ----*/

class DRSCallback
{
public:
   virtual void Progress(int value) = 0;
   virtual ~DRSCallback() {};
};

/*------------------------*/

class DRSBoard;

class ResponseCalibration {
protected:

   class CalibrationData {
   public:
      class CalibrationDataChannel {
      public:
         unsigned char   fLimitGroup[kNumberOfBins];           //!
         float           fMin[kNumberOfBins];                  //!
         float           fRange[kNumberOfBins];                //!
         short           fOffset[kNumberOfBins];               //!
         short           fGain[kNumberOfBins];                 //!
         unsigned short  fOffsetADC[kNumberOfBins];            //!
         short          *fData[kNumberOfBins];                 //!
         unsigned char  *fLookUp[kNumberOfBins];               //!
         unsigned short  fLookUpOffset[kNumberOfBins];         //!
         unsigned char   fNumberOfLookUpPoints[kNumberOfBins]; //!
         float          *fTempData;                            //!

      private:
         CalibrationDataChannel(const CalibrationDataChannel &c);              // not implemented
         CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // not implemented

      public:
         CalibrationDataChannel(int numberOfGridPoints)
         :fTempData(new float[numberOfGridPoints]) {
            int i;
            for (i = 0; i < kNumberOfBins; i++) {
               fData[i] = new short[numberOfGridPoints];
            }
            memset(fLimitGroup,           0, sizeof(fLimitGroup));
            memset(fMin,                  0, sizeof(fMin));
            memset(fRange,                0, sizeof(fRange));
            memset(fOffset,               0, sizeof(fOffset));
            memset(fGain,                 0, sizeof(fGain));
            memset(fOffsetADC,            0, sizeof(fOffsetADC));
            memset(fLookUp,               0, sizeof(fLookUp));
            memset(fLookUpOffset,         0, sizeof(fLookUpOffset));
            memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints));
         }
         ~CalibrationDataChannel() {
            int i;
            delete fTempData;
            for (i = 0; i < kNumberOfBins; i++) {
               delete fData[i];
               delete fLookUp[i];
            }
         }
      };

      bool                    fRead;                                  //!
      CalibrationDataChannel *fChannel[10];                           //!
      unsigned char           fNumberOfGridPoints;                    //!
      int                     fHasOffsetCalibration;                  //!
      float                   fStartTemperature;                      //!
      float                   fEndTemperature;                        //!
      int                    *fBSplineOffsetLookUp[kNumberOfADCBins]; //!
      float                 **fBSplineLookUp[kNumberOfADCBins];       //!
      float                   fMin;                                   //!
      float                   fMax;                                   //!
      unsigned char           fNumberOfLimitGroups;                   //!
      static float            fIntRevers[2 * kBSplineOrder - 2];

   private:
      CalibrationData(const CalibrationData &c);              // not implemented
      CalibrationData &operator=(const CalibrationData &rhs); // not implemented

   public:
      CalibrationData(int numberOfGridPoints);
      ~CalibrationData();
      static int CalculateBSpline(int nGrid, float value, float *bsplines);
      void       PreCalculateBSpline();
      void       DeletePreCalculatedBSpline();
   };

   // General Fields
   DRSBoard        *fBoard;

   double           fPrecision;

   // Fields for creating the Calibration
   bool             fInitialized;
   bool             fRecorded;
   bool             fFitted;
   bool             fOffset;
   bool             fCalibrationValid[2];

   int              fNumberOfPointsLowVolt;
   int              fNumberOfPoints;
   int              fNumberOfMode2Bins;
   int              fNumberOfSamples;
   int              fNumberOfGridPoints;
   int              fNumberOfXConstPoints;
   int              fNumberOfXConstGridPoints;
   double           fTriggerFrequency;
   int              fShowStatistics;
   FILE            *fCalibFile;

   int              fCurrentLowVoltPoint;
   int              fCurrentPoint;
   int              fCurrentSample;
   int              fCurrentFitChannel;
   int              fCurrentFitBin;

   float           *fResponseX[10][kNumberOfBins];
   float           *fResponseY;
   unsigned short **fWaveFormMode3[10];
   unsigned short **fWaveFormMode2[10];
   unsigned short **fWaveFormOffset[10];
   unsigned short **fWaveFormOffsetADC[10];
   unsigned short  *fSamples;
   int             *fSampleUsed;

   float           *fPntX[2];
   float           *fPntY[2];
   float           *fUValues[2];
   float           *fRes[kNumberOfBins];
   float           *fResX[kNumberOfBins];

   double          *fXXFit;
   double          *fYYFit;
   double          *fWWFit;
   double          *fYYFitRes;
   double          *fYYSave;
   double          *fXXSave;
   double          fGainMin;
   double          fGainMax;

   float          **fStatisticsApprox;
   float          **fStatisticsApproxExt;

   // Fields for applying the Calibration
   CalibrationData *fCalibrationData[kNumberOfChips];

private:
         ResponseCalibration(const ResponseCalibration &c);              // not implemented
         ResponseCalibration &operator=(const ResponseCalibration &rhs); // not implemented

public:
   ResponseCalibration(DRSBoard* board);
   ~ResponseCalibration();

   void   SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins,
                                   int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints,
                                   int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0);
   void   ResetCalibration();
   bool   RecordCalibrationPoints(int chipNumber);
   bool   RecordCalibrationPointsV3(int chipNumber);
   bool   RecordCalibrationPointsV4(int chipNumber);
   bool   FitCalibrationPoints(int chipNumber);
   bool   FitCalibrationPointsV3(int chipNumber);
   bool   FitCalibrationPointsV4(int chipNumber);
   bool   OffsetCalibration(int chipNumber);
   bool   OffsetCalibrationV3(int chipNumber);
   bool   OffsetCalibrationV4(int chipNumber);
   double GetTemperature(unsigned int chipIndex);

   bool   WriteCalibration(unsigned int chipIndex);
   bool   WriteCalibrationV3(unsigned int chipIndex);
   bool   WriteCalibrationV4(unsigned int chipIndex);
   bool   ReadCalibration(unsigned int chipIndex);
   bool   ReadCalibrationV3(unsigned int chipIndex);
   bool   ReadCalibrationV4(unsigned int chipIndex);
   bool   Calibrate(unsigned int chipIndex, unsigned int channel, float *adcWaveform,
                    float *uWaveform, float threshold, bool offsetCalib);
   bool   Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, unsigned short *uWaveform,
                    int triggerCell, float threshold, bool offsetCalib);
   bool   SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform,
                            unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel);
   bool   IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; }
   double GetPrecision() const { return fPrecision; };

   double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; };
   double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; };
... 336 more lines ...
ELOG V3.1.4-80633ba