DRS4 Forum
  DRS4 Discussion Forum, Page 23 of 46  Not logged in ELOG logo
ID Date Author Subjectdown
  110   Tue Oct 12 03:53:37 2010 Jinhong WangReference design for DRS4 active input buffer

Stefan Ritt wrote:

The design of high frequency differential input stages with the DRS4 is a challenge, since the chip draws quite some current at the input (up to 1 mA at 5 GSPS), which must be sourced by the input buffer. A simple transformer as used in the DRS4 Evaluation Board 2.0 limits the bandwidth to 220 MHz. In meantime two active input stages have been worked out and successfully been tested, both utilizing the THS4508 differential amplifier. The first design is AC-coupled and uses less power, the second design is DC-coupled and uses more power with the benefit of delivering a higher bandwidth.

Both designs use a clamping diode at the input as a protection against high voltage spikes at the input. We used a RCLAMP0502B diode from SEMTECH, but any fast voltage suppressor diode will do the job. 

The CMOFS input to the THS4508 set the common mode of the differential amplifier. In the AC version the level is set to mid-rail (2.5V), in the DC version it's set to 1.8V to match the input range of the DRS4.

The CAL+ and CAL- signals are used to bias the inputs to a well-defined DC level and can also be used to calibrate the chip. For bipolar inputs, they are both set to 0.8V. A positive 0.5V input pulse then drives DRS_IN+ to (0.8+0.25)V = 1.05V and DRS_IN- to (0.8-0.25)V = 0.55V. A negative 0.5V pulse then drives then DRS_IN+ to 0.55V and DRS_IN- to 1.05V. With ROFS=1.6V, the full dynamic range of the DRS4 is then used. Note that the THS4508 has a gain of 2, and the input has a -6dB voltage divider to compensate for that. To use other input ranges, such as -1V...0V, the CAL+ and CAL- signals can be adjusted accordingly. Note that the inputs of the DRS4 must always be between 0.1V and 1.5V.

 

AC-coupled version

ac.png
                                                                                                                                                                                                                                     (click to enlarge)

Power supply: +5 V 40 mA

Bandwidth (-3dB): 600 MHz

CMOFS: 2.5 V

Transfer function:

ac_bw.png
                                                                                                                                                            (click to enlarge)

The transfer function was measured by applying a fixed amplitude sine wave to the input, and measuring the peak-to-peak value of the read out waveform with the DRSOsc application.

DC-coupled Version

The DC-coupled version has a slightly higher power consumption since there is a constant current flowing through the output into the DRS4 chip. On the other hand, the bandwidth is a bit higher and the peaking around 400 MHz is a bit smaller. The input is still AC-coupled, so both positive and negative pulses can be accepted. 

dc.png
                                                                                                                                                                                                                             (click to enlarge)

Power supply: +5 V 115 mA

Bandwidth (-3dB): 800 MHz

CMOFS: 1.8 V

Transfer function:

dc_bw.png
                                                                                                                                                              (click to enlarge)

Achievable performance

With the active input stage, much faster rise- and fall times can be achieved. Following picture shows a signal from a external clock having a fall time of about 300 ps being recorded with the AC-coupled version of the active input stage. The fall time of the recorded signal is about 800 ps, which is about the minimum which can be achieved with the AC-coupled version. The DC-coupled version achieves about 700ps.

DRS4_ft_V3.jpg

 Hi, stefan,

     In the DC coupled version of the analog drivers for DRS4 input in Eval. Board V3, you mentioned that CMOFS of THS4508 was set to 1.8V to match the input range of DRS4, however, will this clash with the requirements of  DRS4 input voltage between 0.1 V ~1.5V ? The output of THS4508 can easily rise beyond 1.5V for CMOFS=1.8V. I also noticed the resister paris R13/R15, R14/R16 was added among the output of THS4508 and the inputs of DRS4, were these resister pairs were used to attenuate the level of THS4508 output signal (a half ? ) to match the input requirements of DRS4? Maybe I have some misunderstanding about it.

  111   Tue Nov 16 16:38:06 2010 Stefan RittReference design for DRS4 active input buffer

Jinhong Wang wrote:

 

 Hi, stefan,

 

     In the DC coupled version of the analog drivers for DRS4 input in Eval. Board V3, you mentioned that CMOFS of THS4508 was set to 1.8V to match the input range of DRS4, however, will this clash with the requirements of  DRS4 input voltage between 0.1 V ~1.5V ? The output of THS4508 can easily rise beyond 1.5V for CMOFS=1.8V. I also noticed the resister paris R13/R15, R14/R16 was added among the output of THS4508 and the inputs of DRS4, were these resister pairs were used to attenuate the level of THS4508 output signal (a half ? ) to match the input requirements of DRS4? Maybe I have some misunderstanding about it.

 

No you are right about that. The THS4508 has a gain of +2, and by using the resistor pairs we do

1) Reduce the gain back to unity

2) Reduce the input DC level from 1.8V to 0.9V to match the input range

3) Terminate the signals at the input of the DRS chip to minimize reflections

I know this is not so obvious from the schematic, so thanks for asking.

- Stefan 

  40   Sun Feb 21 13:41:35 2010 Stefan RittReal Time Conference 2010

Hello,

may I draw your attention to the upcoming Real Time Conference 2010, taking place in Lisbon, Portugal, May 23rd to May 28th, 2010.

http://rt2010.ipfn.ist.utl.pt/

Several groups which are developing DRS4 electronics will come to this conference and present their work, so it will be a good opportunity to exchange ideas and experiences. There will also be a short course on digital pulse shape processing, which is highly relevant for our field.

Looking forward to see you in Lisbon,

    Stefan 

  48   Thu Mar 4 19:14:10 2010 Hao HuanReadout of DRS Data

Hi Stefan,

    thanks to your help I can now successfully keep the Domino wave running at a stable frequency and maintain the channel cascading information in the Write Shift Register. (Since you told me WSR always reads and writes at the same time, I think I need to rewrite the information back every time after reading out from WSR to decide from which channel my data come, don't I?)

    However I'm still having difficulty in reading out from the DRS cells. I use the ROI readout mode and assume as long as I give a pulse on RSRLOAD the data will come out one by one. However, what I get is just a constant with some noise, which seems I'm always reading from the same cell. Actually I'm not very clear about how it works. What's the mechanism for RSRLOAD  and do I have to initialize the Read Shift Register to use the ROI mode? Also I read in the datasheet that WSROUT will give RSR output when DWRITE is low. Sometimes I see some random bits from this output and sometimes I see all zero's. What is the reasonable output I should see from WSROUT, say, when I'm running in the transparent mode with DWRITE low?

    Thank you very much!

 

  49   Fri Mar 5 23:29:04 2010 Hao HuanReadout of DRS Data

Hao Huan wrote:

Hi Stefan,

    thanks to your help I can now successfully keep the Domino wave running at a stable frequency and maintain the channel cascading information in the Write Shift Register. (Since you told me WSR always reads and writes at the same time, I think I need to rewrite the information back every time after reading out from WSR to decide from which channel my data come, don't I?)

    However I'm still having difficulty in reading out from the DRS cells. I use the ROI readout mode and assume as long as I give a pulse on RSRLOAD the data will come out one by one. However, what I get is just a constant with some noise, which seems I'm always reading from the same cell. Actually I'm not very clear about how it works. What's the mechanism for RSRLOAD  and do I have to initialize the Read Shift Register to use the ROI mode? Also I read in the datasheet that WSROUT will give RSR output when DWRITE is low. Sometimes I see some random bits from this output and sometimes I see all zero's. What is the reasonable output I should see from WSROUT, say, when I'm running in the transparent mode with DWRITE low?

    Thank you very much!

 

Hi Stefan,

    I tried again and confirmed the problem... In the full readout mode I could successfully read out all the data, but in the ROI mode if I naively apply a pulse at RSRLOAD the results are not right. Is there anything I should be careful about in the ROI readout mode?

    Thanks!

 

  52   Thu Mar 11 11:45:52 2010 Stefan RittReadout of DRS Data

Hao Huan wrote:

Hi Stefan,

    thanks to your help I can now successfully keep the Domino wave running at a stable frequency and maintain the channel cascading information in the Write Shift Register. (Since you told me WSR always reads and writes at the same time, I think I need to rewrite the information back every time after reading out from WSR to decide from which channel my data come, don't I?)

Yes you do. But if you have WSRLOOP=1 in the config register, this is done automatically. So the SR output is visible at the pin and will be fed back into the input.

Hao Huan wrote:

    However I'm still having difficulty in reading out from the DRS cells. I use the ROI readout mode and assume as long as I give a pulse on RSRLOAD the data will come out one by one. 

That's not correct. Have a look at Figure 14 of the datasheet. Do you see a single RSRLOAD pulse or many? There is only one RSRLOAD pulse to initialize the readout shift register, then the cells are clocked by SRCLK pulses. 

Hao Huan wrote:

Also I read in the datasheet that WSROUT will give RSR output when DWRITE is low. Sometimes I see some random bits from this output and sometimes I see all zero's. What is the reasonable output I should see from WSROUT, say, when I'm running in the transparent mode with DWRITE low? 

A single RSRLOAD pulse loads the RSR with a "1" at the domino stop position and "0" in all other places. A pulse on SRCLK shifts this "1" down the RSR. When it arrives at cell #1023, it will be visible for one clock cycle at WSROUT. The "double" functionality of WSROUT has the following background: Assume you use channel cascading 2x2048. Now the domino wave stopps in cell 1020 of the first channel for example. You have to read cells 1020,1021,1022,1024 of the first channel, then you continue with 0,1,2 on the second channel. But how do you know that you have to switch channels after the first four clock cycles? The SROUT output encodes the stop position (in this case 1020), but it needs 10 clock cycles before the information is available, so you don't have it after four cycles. That's where WSROUT comes into play: Since it outputs RSR bit by bit, it will show three "0", then a "1", when you are at cell 1023. Then you know that you have to switch channels immediately. That's why I output RSR via WSROUT if DWRITE is low.

 

  676   Thu Mar 22 14:36:01 2018 Phan Van ChuanRead the CalibrateWaveform

Helo
I'm building an application for reading waveforms from the DRS4 board to PC. However, I am having problems reading calibration data from EEPROM on DRS4 board. The calibration data is read through the function reference:
void DRSBoard :: ReadCalibration (void)
...
      ReadEEPROM (1, buf, 1024 * 32);
      for (i = 0; i <8; i ++)
         for (j = 0; j <1024; j ++) {
            fCellOffset [i] [j] = buf [(i * 1024 + j) * 2];
            fCellGain [i] [j] = buf [(i * 1024 + j) * 2 + 1] / 65535.0*0.4+0.7;
         }
      
      ReadEEPROM (2, buf, 1024 * 32);
      for (i = 0; i <8; i ++)
         for (j = 0; j <1024; j ++)
            fCellOffset2 [i] [j] = buf [(i * 1024 + j) * 2];
...
The Calibrate Waveform is performed by:
int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
.....
         for (j = 0; j < n_bins; j++) {
            value = adcWaveform[j] - fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
            value = value / fCellGain[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
            if (offsetCalib && channel != 8)
               value = value - fCellOffset2[channel+chipIndex*9][j*skip] + 32768;
...
. Because the calibration data reads incorrectly, the Calibrate Waveform does not do it.
Can read calibration data from EEPROM by any command via Oscilloscope application or DRS Command Line Interface application?
Thank you for your help!!!!

  677   Fri Mar 23 09:39:55 2018 Stefan RittRead the CalibrateWaveform

You don't have to read and calibrate the waveforms in your user code, but can rely on the DRS.cpp library to do that. Just look at the drs_exam.cpp program coming with the distribution. It uses the function b->GetWave() to retrieve the calibrated waveform. If you like, you can look into that function to learn how to apply the calibration, but I can tell you that it's a bit complicated. Since each event starts at an arbitrary stop cell in the DRS4, you have to "rotate" the calibration array. Then you do actually four calibrations in a row (cell, readout, gain and range).

Stefan

Phan Van Chuan wrote:

Helo
I'm building an application for reading waveforms from the DRS4 board to PC. However, I am having problems reading calibration data from EEPROM on DRS4 board. The calibration data is read through the function reference:
void DRSBoard :: ReadCalibration (void)
...
      ReadEEPROM (1, buf, 1024 * 32);
      for (i = 0; i <8; i ++)
         for (j = 0; j <1024; j ++) {
            fCellOffset [i] [j] = buf [(i * 1024 + j) * 2];
            fCellGain [i] [j] = buf [(i * 1024 + j) * 2 + 1] / 65535.0*0.4+0.7;
         }
      
      ReadEEPROM (2, buf, 1024 * 32);
      for (i = 0; i <8; i ++)
         for (j = 0; j <1024; j ++)
            fCellOffset2 [i] [j] = buf [(i * 1024 + j) * 2];
...
The Calibrate Waveform is performed by:
int DRSBoard::CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, float threshold, bool offsetCalib)
.....
         for (j = 0; j < n_bins; j++) {
            value = adcWaveform[j] - fCellOffset[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
            value = value / fCellGain[channel+chipIndex*9][(j*skip + triggerCell) % kNumberOfBins];
            if (offsetCalib && channel != 8)
               value = value - fCellOffset2[channel+chipIndex*9][j*skip] + 32768;
...
. Because the calibration data reads incorrectly, the Calibrate Waveform does not do it.
Can read calibration data from EEPROM by any command via Oscilloscope application or DRS Command Line Interface application?
Thank you for your help!!!!

 

  393   Mon Nov 17 16:36:18 2014 Mickey ChiuRaspberry Pi drsosc does not exit properly

When running drsosc on a raspberry pi, it seems the exit doesn't seem to work at all.  This is true for the "exit" button on the window, or the file menu exit, or the "x" on the window.  I end up having to kill drsosc manually from the command line.  This wouldn't be such a bad thing except that it doesn't seem to store any settings when killed in this way.  I'm wondering if anyone else sees the same thing, or if there is a fix out there, before I go and delve into why.

  394   Tue Nov 25 14:06:34 2014 Stefan RittRaspberry Pi drsosc does not exit properly

Mickey Chiu wrote:

When running drsosc on a raspberry pi, it seems the exit doesn't seem to work at all.  This is true for the "exit" button on the window, or the file menu exit, or the "x" on the window.  I end up having to kill drsosc manually from the command line.  This wouldn't be such a bad thing except that it doesn't seem to store any settings when killed in this way.  I'm wondering if anyone else sees the same thing, or if there is a fix out there, before I go and delve into why.

Unfortunately I don't have a pi here right now, so I cannot reproduce your problem. I checked on a linux system and it worked fine with wxWidgets 3.0.1 and GTK2 2.20. The wxWidget library sends an wxID_EXIT event to DOFrame::OnExit, which then closes the window. The destructor of DOFrame then calls SaveConfig() to save the current settings. Maybe you can debug this.

/Stefan 

  631   Fri Oct 13 03:39:01 2017 Jonathan WapmanRaspberry Pi Connection Failure

I am currently attempting to use a raspberry pi to connect to the DRS 4 board. I whenever I try to use the DRS Command Line TOol, Revision 21435 to connect to the drs board, I get the error

"musb_open: libusb_open() error -3"

"USB successfully scanned, but no boards found"

"No DRS Boards Found".

I successfully compiled the libusb driver before compiling the drs software 5.0.6, and installed all other listed packages in the install instructions.

  632   Mon Oct 16 15:35:22 2017 Stefan RittRaspberry Pi Connection Failure

Have you tried as root? Maybe you miss some permissions.

Stefan

Jonathan Wapman wrote:

I am currently attempting to use a raspberry pi to connect to the DRS 4 board. I whenever I try to use the DRS Command Line TOol, Revision 21435 to connect to the drs board, I get the error

"musb_open: libusb_open() error -3"

"USB successfully scanned, but no boards found"

"No DRS Boards Found".

I successfully compiled the libusb driver before compiling the drs software 5.0.6, and installed all other listed packages in the install instructions.

 

  76   Wed May 5 22:30:50 2010 Ignacio Diéguez EstremeraRandom noise spec in datasheet

Hi,

According to DRS4's datasheet, the random noise is 0.35mVrms. Is this the input equivalent noise voltage? It is computed over the 0-950MHz frequency band?

Regards.

  77   Thu May 6 08:15:39 2010 Stefan RittRandom noise spec in datasheet

Ignacio Diéguez Estremera wrote:

Hi,

According to DRS4's datasheet, the random noise is 0.35mVrms. Is this the input equivalent noise voltage? It is computed over the 0-950MHz frequency band?

Regards.

You cannot compare the DRS4 noise directly with an amplifier for example. The noise mainly comes from variations of the charge injection into the storage cells, and some noise during the readout process, which happens in a completely different frequency domain than the sampling.

So what I did is to keep the inputs open, measure a 1024-bin waveform, and compute the RMS of this waveform. So I believe that this is kind of equivalent noise voltage from 1-950 MHz. It does not start from zero since very low frequency noise (like 50 Hz) just causes a baseline shift and does not influence the RMS, but this is not so important since in most applications people do an event-by-event baseline subtraction to get rid of low frequency noise in their apparatus. The 0.35 mV RMS also depend on the electronics around the chip. On our USB evaluation board the noise it typically smaller (0.31 mV RMS), while in some VME board we measure 0.42 mV RMS. If you do the perfect analog design around the chip, you can maybe push this maybe even lower.

  262   Tue Jun 18 14:19:39 2013 Stefan RittROOT program to decode binary data from DRSOsc

Please find attached a simple ROOT based program (http://root.cern.ch) to decode binary data from the DRSOsc program. It assumes that all four channels were recorded. If this is not the case, the program can be adjusted accordingly.

To use it, simply type (assuming that you have written a data file "test.dat" with DRSOsc):

root [0] .L decode.C+
Info in <TUnixSystem::ACLiC>: creating shared library /tmp/./decode_C.so
root [1] decode("test");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
1927 events processed
"test.root" written
root [2] 

If you have turned on the clock on channel4 of the DRS4 evaluation board, it will produce a plot like this:
 
c1.gif 

 

/Stefan

Attachment 1: decode.C
#include <string.h>
#include <stdio.h>
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include <iostream>

struct Header_t {
   char           event_header[4];
   unsigned int   serial_number;
   unsigned short year;
   unsigned short month;
   unsigned short day;
   unsigned short hour;
   unsigned short minute;
   unsigned short second;
   unsigned short millisecond;
   unsigned short reserved1;
   float time[1024];
};

struct Waveform_t {
   char           chn1_header[4];
   unsigned short chn1[1024];
   char           chn2_header[4];
   unsigned short chn2[1024];
   char           chn3_header[4];
   unsigned short chn3[1024];
   char           chn4_header[4];
   unsigned short chn4[1024];
};

void decode(char *filename) {
   Header_t header;
   Waveform_t waveform;
   Double_t t[1024], chn1[1024], chn2[1024], chn3[1024], chn4[1024];
   Int_t n;

   // open the binary waveform file
   FILE *f = fopen(Form("%s.dat", filename), "r");

   //open the root file
   TFile *outfile = new TFile(Form("%s.root", filename), "RECREATE");
   
   // define the rec tree
   TTree *rec = new TTree("rec","rec");
   rec->Branch("t", &t   ,"t[1024]/D");  
   rec->Branch("chn1", &chn1 ,"chn1[1024]/D");
   rec->Branch("chn2", &chn2 ,"chn2[1024]/D");
   rec->Branch("chn3", &chn3 ,"chn3[1024]/D");
   rec->Branch("chn4", &chn4 ,"chn4[1024]/D");
  
   // loop over all events in data file
   for (n=0 ; fread(&header, sizeof(header), 1, f) > 0; n++) {

      // decode time      
      for (Int_t i=0; i<1024; i++)
         t[i] = (Double_t) header.time[i];
      
      fread(&waveform, sizeof(waveform), 1, f);
      
      // decode amplitudes in mV
      for (Int_t i=0; i<1024; i++) {
         chn1[i] = (Double_t) ((waveform.chn1[i]) / 65535. - 0.5) * 1000;   
         chn2[i] = (Double_t) ((waveform.chn2[i]) / 65535. - 0.5) * 1000;   
         chn3[i] = (Double_t) ((waveform.chn3[i]) / 65535. - 0.5) * 1000;   
         chn4[i] = (Double_t) ((waveform.chn4[i]) / 65535. - 0.5) * 1000;   
      }
      rec->Fill();
   }
   
   // draw channel #4
   rec->Draw("chn4:t");
   
   // print number of events
   cout<<n<<" events processed"<<endl;
   cout<<"\""<<Form("%s.root", filename)<<"\" written"<<endl;
   
   // save and close root file
   rec->Write();
   outfile->Close();
}
  361   Wed Jul 30 17:05:06 2014 Stefan RittROOT program to decode binary data from DRSOsc

Stefan Ritt wrote:

Please find attached a simple ROOT based program (http://root.cern.ch) to decode binary data from the DRSOsc program. It assumes that all four channels were recorded. If this is not the case, the program can be adjusted accordingly.

To use it, simply type (assuming that you have written a data file "test.dat" with DRSOsc):

root [0] .L decode.C+
Info in <TUnixSystem::ACLiC>: creating shared library /tmp/./decode_C.so
root [1] decode("test");
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
1927 events processed
"test.root" written
root [2] 

If you have turned on the clock on channel4 of the DRS4 evaluation board, it will produce a plot like this:
 
c1.gif 

 

/Stefan

I updated this ROOT program for the new format used with the V5 boards. It's now called "read_binary.C". Usage stays the same. There is also a standalone C program "read_binary.cpp". Both are attached. 

Attachment 1: read_binary.C
/*
 
   Name:           read_binary.C
   Created by:     Stefan Ritt <stefan.ritt@psi.ch>
   Date:           July 30th, 2014
 
   Purpose:        Example program under ROOT to read a binary data file written 
                   by the DRSOsc program. Decode time and voltages from waveforms 
                   and display them as a graph. Put values into a ROOT Tree for 
                   further analysis.
 
                   To run it, do:
 
                   - Crate a file test.dat via the "Save" button in DRSOsc
                   - start ROOT
                   root [0] .L read_binary.C+
                   root [1] decode("test.dat");
 
*/
 

#include <string.h>
#include <stdio.h>
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TGraph.h"
#include "TCanvas.h"
#include "Getline.h"

typedef struct {
  char           time_header[4];
  char           bn[2];
  unsigned short board_serial_number;
} THEADER;

typedef struct {
  char           event_header[4];
  unsigned int   event_serial_number;
  unsigned short year;
  unsigned short month;
  unsigned short day;
  unsigned short hour;
  unsigned short minute;
  unsigned short second;
  unsigned short millisecond;
  unsigned short reserved1;
  char           bs[2];
  unsigned short board_serial_number;
  char           tc[2];
  unsigned short trigger_cell;
} EHEADER;

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

void decode(char *filename) {
   THEADER th;
   EHEADER eh;
   char hdr[4];
   unsigned short voltage[1024];
   double waveform[4][1024], time[4][1024];
   float bin_width[4][1024];
   char rootfile[256];
   int i, j, ch, n, chn_index;
   double t1, t2, dt;

   // open the binary waveform file
   FILE *f = fopen(Form("%s", filename), "r");
   if (f == NULL) {
      printf("Cannot find file \'%s\'\n", filename);
      return;
   }

   //open the root file
   strcpy(rootfile, filename);
   if (strchr(rootfile, '.'))
      *strchr(rootfile, '.') = 0;
   strcat(rootfile, ".root");
   TFile *outfile = new TFile(rootfile, "RECREATE");
   
   // define the rec tree
   TTree *rec = new TTree("rec","rec");
   rec->Branch("t1", time[0]     ,"t1[1024]/D");  
   rec->Branch("t2", time[1]     ,"t2[1024]/D");  
   rec->Branch("t3", time[2]     ,"t3[1024]/D");  
   rec->Branch("t4", time[3]     ,"t4[1024]/D");  
   rec->Branch("w1", waveform[0] ,"w1[1024]/D");
   rec->Branch("w2", waveform[1] ,"w2[1024]/D");
   rec->Branch("w3", waveform[2] ,"w3[1024]/D");
   rec->Branch("w4", waveform[3] ,"w4[1024]/D");
   
   // create canvas
   TCanvas *c1 = new TCanvas();
   
   // create graph
   TGraph *g = new TGraph(1024, (double *)time[0], (double *)waveform[0]);

   // read time header
   fread(&th, sizeof(th), 1, f);
   printf("Found data for board #%d\n", th.board_serial_number);

   // read time bin widths
   memset(bin_width, sizeof(bin_width), 0);
   for (ch=0 ; ch<5 ; ch++) {
      fread(hdr, sizeof(hdr), 1, f);
      if (hdr[0] != 'C') {
         // event header found
         fseek(f, -4, SEEK_CUR);
         break;      
      }
      i = hdr[3] - '0' - 1;
      printf("Found timing calibration for channel #%d\n", i+1);
      fread(&bin_width[i][0], sizeof(float), 1024, f);
   }

   // loop over all events in data file
   for (n=0 ; n<5 ; n++) {
      // read event header
      i = fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;
         
      printf("Found event #%d\n", eh.event_serial_number);

      // reach channel data
      for (ch=0 ; ch<5 ; ch++) {
         i = fread(hdr, sizeof(hdr), 1, f);
         if (i < 1)
            break;
         if (hdr[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;      
         }
         chn_index = hdr[3] - '0' - 1;
         fread(voltage, sizeof(short), 1024, f);
         
         for (i=0 ; i<1024 ; i++) {
            // convert data to volts
            waveform[chn_index][i] = (voltage[i] / 65536. - 0.5);
            
            // calculate time for this cell
            for (j=0,time[chn_index][i]=0 ; j<i ; j++)
              time[chn_index][i] += bin_width[chn_index][(j+eh.trigger_cell) % 1024];            
         }
      }
    
      // align cell #0 of all channels
      t1 = time[0][(1024-eh.trigger_cell) % 1024];
      for (ch=1 ; ch<4 ; ch++) {
         t2 = time[ch][(1024-eh.trigger_cell) % 1024];
         dt = t1 - t2;
         for (i=0 ; i<1024 ; i++)
            time[ch][i] += dt;
      }

      // fill root tree
      rec->Fill();
      
      // fill graph
      for (i=0 ; i<1024 ; i++)
         g->SetPoint(i, time[0][i], waveform[0][i]);
      
      // draw graph and wait for user click
      g->Draw("ACP");
      c1->Update();
      gPad->WaitPrimitive();
   }

   // print number of events
   printf("%d events processed, \"%s\" written.\n", n, rootfile);
   
   // save and close root file
   rec->Write();
   outfile->Close();
}
Attachment 2: read_binary.cpp
/*
   Name:           read_binary.cpp
   Created by:     Stefan Ritt <stefan.ritt@psi.ch>
   Date:           July 30th, 2014

   Purpose:        Example file to read binary data saved by DRSOsc.
 
   Compile and run it with:
 
      gcc -o read_binary read_binary.cpp
 
      ./read_binary <filename>

   This program assumes that a pulse from a signal generator is split
   and fed into channels #1 and #2. It then calculates the time difference
   between these two pulses to show the performance of the DRS board
   for time measurements.

   $Id: read_binary.cpp 21438 2014-07-30 15:00:17Z ritt $
*/

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <math.h>

typedef struct {
   char           time_header[4];
   char           bn[2];
   unsigned short board_serial_number;
} THEADER;

typedef struct {
   char           event_header[4];
   unsigned int   event_serial_number;
   unsigned short year;
   unsigned short month;
   unsigned short day;
   unsigned short hour;
   unsigned short minute;
   unsigned short second;
   unsigned short millisecond;
   unsigned short reserved1;
   char           bs[2];
   unsigned short board_serial_number;
   char           tc[2];
   unsigned short trigger_cell;
} EHEADER;

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

int main(int argc, const char * argv[])
{
   THEADER th;
   EHEADER eh;
   char hdr[4];
   unsigned short voltage[1024];
   double waveform[4][1024], time[4][1024];
   float bin_width[4][1024];
   char rootfile[256];
   int i, j, ch, n, chn_index;
   double t1, t2, dt;
   char filename[256];

   int ndt;
   double threshold, sumdt, sumdt2;
   
   if (argc > 1)
      strcpy(filename, argv[1]);
   else {
      printf("Usage: read_binary <filename>\n");
      return 0;
   }
   
   // open the binary waveform file
   FILE *f = fopen(filename, "r");
   if (f == NULL) {
      printf("Cannot find file \'%s\'\n", filename);
      return 0;
   }

   // read time header
   fread(&th, sizeof(th), 1, f);
   printf("Found data for board #%d\n", th.board_serial_number);

   // read time bin widths
   memset(bin_width, sizeof(bin_width), 0);
   for (ch=0 ; ch<5 ; ch++) {
      fread(hdr, sizeof(hdr), 1, f);
      if (hdr[0] != 'C') {
         // event header found
         fseek(f, -4, SEEK_CUR);
         break;
      }
      i = hdr[3] - '0' - 1;
      printf("Found timing calibration for channel #%d\n", i+1);
      fread(&bin_width[i][0], sizeof(float), 1024, f);
   }
   
   // initialize statistics
   ndt = 0;
   sumdt = sumdt2 = 0;
   
   // loop over all events in the data file
   for (n= 0 ; ; n++) {
      // read event header
      i = fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;
      
      printf("Found event #%d\n", eh.event_serial_number);
      
      // reach channel data
      for (ch=0 ; ch<5 ; ch++) {
         i = fread(hdr, sizeof(hdr), 1, f);
         if (i < 1)
            break;
         if (hdr[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;
         }
         chn_index = hdr[3] - '0' - 1;
         fread(voltage, sizeof(short), 1024, f);
         
         for (i=0 ; i<1024 ; i++) {
            // convert data to volts
            waveform[chn_index][i] = (voltage[i] / 65536. - 0.5);
            
            // calculate time for this cell
            for (j=0,time[chn_index][i]=0 ; j<i ; j++)
               time[chn_index][i] += bin_width[chn_index][(j+eh.trigger_cell) % 1024];
         }
      }
      
      
      // align cell #0 of all channels
      t1 = time[0][(1024-eh.trigger_cell) % 1024];
      for (ch=1 ; ch<4 ; ch++) {
         t2 = time[ch][(1024-eh.trigger_cell) % 1024];
         dt = t1 - t2;
         for (i=0 ; i<1024 ; i++)
            time[ch][i] += dt;
      }
      
      t1 = t2 = 0;
      threshold = 0.3;
      
      // find peak in channel 1 above threshold
      for (i=0 ; i<1022 ; i++)
         if (waveform[0][i] < threshold && waveform[0][i+1] >= threshold) {
            t1 = (threshold-waveform[0][i])/(waveform[0][i+1]-waveform[0][i])*(time[0][i+1]-time[0][i])+time[0][i];
            break;
         }
      
      // find peak in channel 2 above threshold
      for (i=0 ; i<1022 ; i++)
         if (waveform[1][i] < threshold && waveform[1][i+1] >= threshold) {
            t2 = (threshold-waveform[1][i])/(waveform[1][i+1]-waveform[1][i])*(time[1][i+1]-time[1][i])+time[1][i];
            break;
         }
      
      // calculate distance of peaks with statistics
      if (t1 > 0 && t2 > 0) {
         ndt++;
         dt = t2 - t1;
         sumdt += dt;
         sumdt2 += dt*dt;
      }
   }
   
   // print statistics
   printf("dT = %1.3lfns +- %1.1lfps\n", sumdt/ndt, 1000*sqrt(1.0/(ndt-1)*(sumdt2-1.0/ndt*sumdt*sumdt)));
   
   return 1;
}

  747   Fri Mar 8 19:35:11 2019 Abaz KryemadhiROOT Macro for newest software

The older root macro did not work for me for data acquired with the newest software.

so for the newest software and multiple boards, I modified the read_binary.cpp into read_binary.C for those who like to use the root macro, see the attachment.  

 

Attachment 1: read_binary.C
/*
 
   Name:           read_binary.C
   Created by:     Stefan Ritt <stefan.ritt@psi.ch>
   Date:           July 30th, 2014
   Modified By:    Abaz Kryemadhi
   Date:           March 7th, 2019
 
   Purpose:        Example program under ROOT to read a binary data file written 
                   by the DRSOsc program. Decode time and voltages from waveforms 
                   and display them as a graph. Put values into a ROOT Tree for 
                   further analysis.
 
                   To run it, do:
 
                   - Crate a file test.dat via the "Save" button in DRSOsc
                   - start ROOT (type root)
                   root [0] .L read_binary.C+
                   root [1] decode("test.dat");
 
*/
 

#include <fcntl.h>
#include <unistd.h>
#include <math.h>


#include <string.h>
#include <stdio.h>
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TGraph.h"
#include "TCanvas.h"
#include "Getline.h"
#include "TAxis.h"

typedef struct {
   char           tag[3];
   char           version;
} FHEADER;

typedef struct {
   char           time_header[4];
} THEADER;

typedef struct {
   char           bn[2];
   unsigned short board_serial_number;
} BHEADER;

typedef struct {
   char           event_header[4];
   unsigned int   event_serial_number;
   unsigned short year;
   unsigned short month;
   unsigned short day;
   unsigned short hour;
   unsigned short minute;
   unsigned short second;
   unsigned short millisecond;
   unsigned short range;
} EHEADER;

typedef struct {
   char           tc[2];
   unsigned short trigger_cell;
} TCHEADER;

typedef struct {
   char           c[1];
   char           cn[3];
} CHEADER;

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

//int main(int argc, const char * argv[])
void decode(char *filename) {

   FHEADER  fh;
   THEADER  th;
   BHEADER  bh;
   EHEADER  eh;
   TCHEADER tch;
   CHEADER  ch;
   
   unsigned int scaler;
   unsigned short voltage[1024];
   double waveform[16][4][1024], time[16][4][1024];
   float bin_width[16][4][1024];
   int i, j, b, chn, n, chn_index, n_boards;
   double t1, t2, dt;
   //char filename[256];
   char rootfile[256];
   int ndt;
   double threshold, sumdt, sumdt2;
   double sum, baseline, max,amplitude1,amplitude2, amplitude3,amplitude4;
   
   // open the binary waveform file
   FILE *f = fopen(filename, "rb");
   if (f == NULL) {
      printf("Cannot find file \'%s\'\n", filename);
      return;
   }
   
   
    //open the root file
   strcpy(rootfile, filename);
   if (strchr(rootfile, '.'))
      *strchr(rootfile, '.') = 0;
   strcat(rootfile, ".root");
   TFile *outfile = new TFile(rootfile, "RECREATE");
   
   // define the rec tree
   TTree *rec = new TTree("rec","rec");
   rec->Branch("t1", time[0][0]     ,"t1[1024]/D");  
   rec->Branch("t2", time[0][1]     ,"t2[1024]/D");  
   rec->Branch("t3", time[0][2]     ,"t3[1024]/D");  
   rec->Branch("t4", time[0][3]     ,"t4[1024]/D");  
   rec->Branch("w1", waveform[0][0] ,"w1[1024]/D");
   rec->Branch("w2", waveform[0][1] ,"w2[1024]/D");
   rec->Branch("w3", waveform[0][2] ,"w3[1024]/D");
   rec->Branch("w4", waveform[0][3] ,"w4[1024]/D");
   rec->Branch("amplitude1", &amplitude1,"amplitude1/D");
   rec->Branch("amplitude2", &amplitude2,"amplitude2/D");
   rec->Branch("amplitude3", &amplitude3,"amplitude3/D");
   rec->Branch("amplitude4", &amplitude4,"amplitude4/D");
   // create canvas
   TCanvas *c1 = new TCanvas();
   
   // create graph
   TGraph *g = new TGraph(1024, (double *)time[0][0], (double *)waveform[0][0]);


   // read file header
   fread(&fh, sizeof(fh), 1, f);
   if (fh.tag[0] != 'D' || fh.tag[1] != 'R' || fh.tag[2] != 'S') {
      printf("Found invalid file header in file \'%s\', aborting.\n", filename);
      return;
   }
   
   if (fh.version != '2') {
      printf("Found invalid file version \'%c\' in file \'%s\', should be \'2\', aborting.\n", fh.version, filename);
      return;
   }

   // read time header
   fread(&th, sizeof(th), 1, f);
   if (memcmp(th.time_header, "TIME", 4) != 0) {
      printf("Invalid time header in file \'%s\', aborting.\n", filename);
      return;
   }

   for (b = 0 ; ; b++) {
      // read board header
      fread(&bh, sizeof(bh), 1, f);
      if (memcmp(bh.bn, "B#", 2) != 0) {
         // probably event header found
         fseek(f, -4, SEEK_CUR);
         break;
      }
      
      printf("Found data for board #%d\n", bh.board_serial_number);
      
      // read time bin widths
      memset(bin_width[b], sizeof(bin_width[0]), 0);
      for (chn=0 ; chn<5 ; chn++) {
         fread(&ch, sizeof(ch), 1, f);
         if (ch.c[0] != 'C') {
            // event header found
            fseek(f, -4, SEEK_CUR);
            break;
         }
         i = ch.cn[2] - '0' - 1;
         printf("Found timing calibration for channel #%d\n", i+1);
         fread(&bin_width[b][i][0], sizeof(float), 1024, f);
         // fix for 2048 bin mode: double channel
         if (bin_width[b][i][1023] > 10 || bin_width[b][i][1023] < 0.01) {
            for (j=0 ; j<512 ; j++)
               bin_width[b][i][j+512] = bin_width[b][i][j];
         }
      }
   }
   n_boards = b;
   
   // initialize statistics
   ndt = 0;
   sumdt = sumdt2 = 0;
   
   // loop over all events in the data file
   for (n=0 ; ; n++) {
      // read event header
      i = (int)fread(&eh, sizeof(eh), 1, f);
      if (i < 1)
         break;
      
      printf("Found event #%d %d %d\n", eh.event_serial_number, eh.second, eh.millisecond);
      
      // loop over all boards in data file
      for (b=0 ; b<n_boards ; b++) {
         
         // read board header
         fread(&bh, sizeof(bh), 1, f);
         if (memcmp(bh.bn, "B#", 2) != 0) {
            printf("Invalid board header in file \'%s\', aborting.\n", filename);
            return;
         }
         
         // read trigger cell
         fread(&tch, sizeof(tch), 1, f);
         if (memcmp(tch.tc, "T#", 2) != 0) {
            printf("Invalid trigger cell header in file \'%s\', aborting.\n", filename);
            return;
         }

         if (n_boards > 1)
            printf("Found data for board #%d\n", bh.board_serial_number);
         
         // reach channel data
         for (chn=0 ; chn<4 ; chn++) {
            
            // read channel header
            fread(&ch, sizeof(ch), 1, f);
            if (ch.c[0] != 'C') {
               // event header found
               fseek(f, -4, SEEK_CUR);
               break;
            }
            chn_index = ch.cn[2] - '0' - 1;
            fread(&scaler, sizeof(int), 1, f);
            fread(voltage, sizeof(short), 1024, f);
            
            for (i=0 ; i<1024 ; i++) {
               // convert data to volts
               waveform[b][chn_index][i] = (voltage[i] / 65536. + eh.range/1000.0 - 0.5);
               
               // calculate time for this cell
               for (j=0,time[b][chn_index][i]=0 ; j<i ; j++)
                  time[b][chn_index][i] += bin_width[b][chn_index][(j+tch.trigger_cell) % 1024];
            }
         }
         
         // align cell #0 of all channels
         t1 = time[b][0][(1024-tch.trigger_cell) % 1024];
         for (chn=1 ; chn<4 ; chn++) {
            t2 = time[b][chn][(1024-tch.trigger_cell) % 1024];
            dt = t1 - t2;
            for (i=0 ; i<1024 ; i++)
               time[b][chn][i] += dt;
         }
         
         t1 = t2 = 0;
         threshold = 0.3;
         
         // find peak in channel 1 above threshold
         for (i=0 ; i<1022 ; i++)
            if (waveform[b][0][i] < threshold && waveform[b][0][i+1] >= threshold) {
               t1 = (threshold-waveform[b][0][i])/(waveform[b][0][i+1]-waveform[b][0][i])*(time[b][0][i+1]-time[b][0][i])+time[b][0][i];
               break;
            }
         
         // find peak in channel 2 above threshold
         for (i=0 ; i<1022 ; i++)
            if (waveform[b][1][i] < threshold && waveform[b][1][i+1] >= threshold) {
               t2 = (threshold-waveform[b][1][i])/(waveform[b][1][i+1]-waveform[b][1][i])*(time[b][1][i+1]-time[b][1][i])+time[b][1][i];
               break;
            }
         
         // calculate distance of peaks with statistics
         if (t1 > 0 && t2 > 0) {
            ndt++;
            dt = t2 - t1;
            sumdt += dt;
            sumdt2 += dt*dt;
         }
     //Find baseline for channel 3 to get amplitude for ch3 
     sum=0.0;
      for (i=0 ; i<10; i++) {
         sum+=waveform[0][2][i];
       } 
       baseline=sum/10;
     //Find amplitude for channel 3 (this is example channel )
     max=-10000.0;
      for (i=0 ; i<1022; i++) {
         if (waveform[b][2][i]>max) {
            max=waveform[b][2][i];
       } 
      }
       amplitude3=max;
     // fill root tree
      rec->Fill();

  //Uncomment the following to see couple waveforms of voltage vs time
  /*   
      // fill graph
      for (i=0 ; i<1024 ; i++)
         g->SetPoint(i, time[b][2][i], waveform[b][2][i]);
      
      // draw graph and wait for user click
... 20 more lines ...
  727   Tue Jan 29 14:43:44 2019 Abaz KryemadhiROOT Macro for data acquired with the newest software

Hello,

Is there a root macro for decoding binary data acquired with the newest software for single board or multi-boards daisy chained?

Cheers,

Abaz

  730   Wed Jan 30 17:08:58 2019 Stefan RittROOT Macro for data acquired with the newest software

This one elog:361 should still work.

Stefan

Abaz Kryemadhi wrote:

Hello,

Is there a root macro for decoding binary data acquired with the newest software for single board or multi-boards daisy chained?

Cheers,

Abaz

 

  663   Fri Mar 2 18:08:55 2018 Steven BlockROI

Hello,

I have a question about how ROI works. From what I have read, it will only save data that ocurs some time [ta] dictated by the user after an event is triggered as well as a small time [tb] before the event. The technical manual seems to indicated that the deadtime assciated with operating in ROI mode can be reduced by the following factor: 

\frac{t_a + t_b }{\frac{N}{Sample Speed}} .

Where N is the number of points in the time window (ex. 2048 or 1024). Is it ok to describe this as:

\frac{N'}{N} 

Where N' is the number of samples in the ROI and N is the same as before.

For example, if I were running at 5Gsps (200ps between samples), only recording 1024 samples per event and I had an signal that lasted 2ns, that means the signal would last 10 samples. If I set the ROI to only save 20 samples around this signal, would my Deadtime go to:

\frac{10}{1024} * 30ns*1024 + 2\mu s = 2.3\mu s? (The second portion of this equation comes from a response I recieved earlier, but I just want to make sure I understand this concept properly)

I recognize that the caveat is that this would work only if the signal was detected during acquistion, which leads to my next question. If no signals were detected in the 1024*200ps time frame in ROI mode, would the DRS4 go dead for 32us (using the factor = 1 from above equation), or would it dump the earliest events in the buffer for the more recent ones until it detects a signal? 

Finally, I assume this functionality can only be utilized with custom electornics with the DRS4, not the evaulation/demo board, please let me know if this is the case. 

Best,

Steven

ELOG V3.1.5-3fb85fa6