// Author: Thomas Hadig (Group EB SLAC Stanford CA USA)
// Last update: $Date: 2003/08/27 19:51:12 $
// Copyright: Thomas Hadig, hadig@slac.stanford.edu

#ifndef __CRTTDC3377BOARD_CXX
#define __CRTTDC3377BOARD_CXX

////////////////////////////////////////////////////////////////////////////////
//
// Cosmic Ray Telescope Data Aquisition Software
//
// generic driver for Camac module: LeCroy 3377 TDC
//
// This module features:
// - 32 channels, 16 bits each
// - read-out is sequentially, i.e. 32 times reading of "channel" 0 
//   gives the 32 values
// - has seven control/test registers (encoded here as channel 1 to 8)
//
////////////////////////////////////////////////////////////////////////////////

#include <iostream>

#include <TSystem.h>

#include <gendriver/tdc3377board.hh>
#include <gendriver/camaccrate.hh>


namespace CRT
 { 
  //{{{}}}
  //{{{  default constructor
   CrtTdc3377Board::CrtTdc3377Board() : CrtTdcAdcBoard()
   {
    // default constructor
    fOk=0;
   }
  //}}}
  //{{{  constructor CrtTdc3377Board(const Char_t *inName, Int_t inBoardNumber, CrtCamacCrate *inCrate)
   CrtTdc3377Board::CrtTdc3377Board(const Char_t *inName, Int_t inBoardNumber, CrtCamacCrate *inCrate)
    : CrtTdcAdcBoard(inName, inBoardNumber, inCrate)
   {
    // constructor
    // inBoardNumber is the number of the Camac slot
    // inCrate       is a pointer to the Camac crate object
    Int_t i=0;
    while (i<7)
     //{{{  fill identity array
     {
      fIdents[i]=inCrate->GetIdentity(inBoardNumber, i);
      i++;
     }
     //}}}
    fOk=1;
   }
  //}}}
  //{{{  destructor
   CrtTdc3377Board::~CrtTdc3377Board()
   {
    // destructor
   }
  //}}}
  
  //{{{  Send
   Int_t CrtTdc3377Board::Send(Int_t inCommand) const
   {
    // sends command to board
    // available commands:
    // CrtTdc3377Board::C_TDC3377_ClearModule 
    // CrtTdc3377Board::C_TDC3377_TestModule
   
    if (fOk!=1) return -1;
    switch (inCommand)
     {
      case C_TDC3377_ClearModule:
       {
        int ret = fInCrate->Send(fIdents[0], 9, 0);
        usleep(200000); // wait > 200ms to module reset
        return ret;
       }
      case C_TDC3377_TestModule:
        return fInCrate->Send(fIdents[0], 25, 0);
     }
    return -1;
   }
  //}}}
  //{{{  Enable
   Int_t CrtTdc3377Board::Enable(Int_t inFlag, Int_t) const
   {
    // enables board features
    // Available features:
    // CrtTdc3377Board::F_TDC3377_LAM (Look-At-Me)
    // CrtTdc3377Board::F_TDC3377_ACQUISITION
   
    if (fOk!=1) return -1;
    switch(inFlag)
     {
      case F_TDC3377_LAM: 
        return fInCrate->Send(fIdents[0], 26, 0);
      case F_TDC3377_ACQUISITION:
        return fInCrate->Send(fIdents[1], 26, 0);
     }
    return -1;
   }
  //}}}
  //{{{  Disable
   Int_t CrtTdc3377Board::Disable(Int_t inFlag, Int_t) const
   {
    // disables board features
    // Available features:
    // CrtTdc3377Board::F_TDC3377_LAM (Look-At-Me)
    // CrtTdc3377Board::F_TDC3377_ACQUISITION
   
    if (fOk!=1) return -1;
    switch(inFlag)
     {
      case F_TDC3377_LAM: 
        return fInCrate->Send(fIdents[0], 24, 0);
      case F_TDC3377_ACQUISITION:
        return fInCrate->Send(fIdents[1], 24, 0);
     }
    return -1;
   }
  //}}}
  //{{{  Clear
   Int_t CrtTdc3377Board::Clear(Int_t inFlag, Int_t) const
   {
    // clears board features
    // Available features:
    // CrtTdc3377Board::F_TDC3377_LAM (Look-At-Me)
   
    if (fOk!=1) return -1;
    switch(inFlag)
     {
      case F_TDC3377_LAM: 
        return fInCrate->Send(fIdents[0], 10, 0);
     }
    return -1;
   }
  //}}}
  //{{{  Test
   Int_t CrtTdc3377Board::Test(Int_t inFlag, Int_t) const
   {
    // tests board features
    // Available features:
    // CrtTdc3377Board::F_TDC3377_LAM (Look-At-Me)
    // CrtTdc3377Board::F_TDC3377_BufferingInProgress
    // CrtTdc3377Board::F_TDC3377_BUSY
    // CrtTdc3377Board::F_TDC3377_EVENT_RDY
    // CrtTdc3377Board::F_TDC3377_FIFO_TAG
   
    if (fOk!=1) return -1;
    switch(inFlag)
     {
      case F_TDC3377_LAM: 
        return fInCrate->Test(fIdents[0], 8);
      case F_TDC3377_BufferingInProgress: 
        return fInCrate->Test(fIdents[0], 27);
      case F_TDC3377_BUSY: 
        return fInCrate->Test(fIdents[1], 27);
      case F_TDC3377_EVENT_RDY:
        return fInCrate->Test(fIdents[2], 27);
      case F_TDC3377_FIFO_TAG:
        return fInCrate->Test(fIdents[3], 27);
     }
    return -1;
   }
  //}}}
  //{{{  Query
   Int_t CrtTdc3377Board::Query(Int_t inChannel, Int_t *outValue) const
   {
    // queries channels
    // available channels:
    // 0: sequentially read data of all 32 channels
    //    return value encodes the value and the channel number
    // 1: control register 0
    // 2: control register 1
    // 3: control register 2
    // 4: control register 3
    // 5: control register 4
    // 6: control register 5
    // 7: CAMAC test register
   
    if (fOk!=1) return -1;
    if (inChannel==0)
      return fInCrate->Read(fIdents[0], 0, outValue);
    if ((inChannel<1)||(inChannel>7)) return -1;
    return fInCrate->Read(fIdents[inChannel-1], 1, outValue);
   }
  //}}}
  //{{{  Assign
   Int_t CrtTdc3377Board::Assign(Int_t inChannel, Int_t inValue) const
   {
    // assigns channels
    // available channels:
    // 0: FIFO
    // 1: control register 0
    // 2: control register 1
    // 3: control register 2
    // 4: control register 3
    // 5: control register 4
    // 6: control register 5
    // 7: FIFO tag bit
   
    if (fOk!=1) return -1;
    if (inChannel==0)
      return fInCrate->Send(fIdents[0], 16, inValue);
    if (inChannel==7)
      return fInCrate->Send(fIdents[1], 16, inValue);
    if ((inChannel<1)||(inChannel>6)) return -1;
    return fInCrate->Send(fIdents[inChannel-1], 17, inValue);
   }
  //}}}
  
  //{{{  Initialize
   Int_t CrtTdc3377Board::Initialize() const
   {
    // initializes the board
    
    Send(C_TDC3377_ClearModule);
    fInCrate->Send(fIdents[0], 30, 0);   // start programming
#  ifdef __CRTTDC3377_SINGLE_WORD
    fInCrate->Send(fIdents[0], 21, 0);   // select common start, single word
#  else
    fInCrate->Send(fIdents[0], 23, 0);   // select common start, double word
#  endif
    fInCrate->Send(fIdents[0], 25, 0);   // load the program
    usleep(200000); // wait > 200ms to let the module to the programming
    while (fInCrate->Test(fIdents[0], 13)==0);  // wait for successfull Xilinx test
    Send(C_TDC3377_ClearModule);
                  //Assign(1, 0x1000);  // Multi-event buffers
#  ifdef __CRTTDC3377_NO_HEADER_WORD
    Assign(1, 0x2000);  // no Multi-event buffers, no header word, leading edge only
#  else
    Assign(1,      0);  // no Multi-event buffers, with header word, leading edge only
#  endif
    Assign(2,      0);  // no MPI
    Assign(3,      0);  // allow 16 hits per TDC
#  ifdef __CRTTDC3377_SINGLE_WORD
    Assign(4, 0x0280);  // no FERA, 320ns time out
#  else
    Assign(4,      0);  // no FERA
#  endif
    Assign(5, 0x0007);  // 350nano-sec time out
    Assign(6,      0);  // no test mode
    return 1;
   }
  //}}}
  //{{{  Prepare
   Int_t CrtTdc3377Board::Prepare() const
   {
    // prepares the board for data taking
    Clear(F_TDC3377_LAM);    // clear LAMs
    Enable(F_TDC3377_LAM);   // enable LAMs
    fInCrate->Send(fIdents[1], 26, 0); // anable data aquisition
    return 1;
   }
  //}}}
  //{{{  HasData
   Int_t CrtTdc3377Board::HasData() const
   {
    // tests whether the module has data available
    return Test(F_TDC3377_LAM);
   }
  //}}}
  //{{{  ReadModule
   Int_t CrtTdc3377Board::ReadModuleAndClear(Int_t *outChannels) const
   {
    // reads all channels and clears the data afterwards.
    // returns only first reported hit in each channel.
    // This is actually the one with the highest time value.

#  ifdef __CRTTDC3377_DEBUG
    // for debugging purposes 
    static int datastore[4000];
    static int fifo[4000];
    int datastorecounter=0;
#  endif

    memset(outChannels,0,32*sizeof(Int_t));
    if (fOk!=1) return -1;

#  if 0
    if (Test(CrtTdc3377Board::F_TDC3377_BUSY)==0)
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}
#  endif
    
    if (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)==1) 
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}

    Int_t value;
    if (Query(0,&value)==0)
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}
    Int_t count=0;
    while (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)!=1)
     //{{{  forever
     {
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#     ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#     endif
        
      Int_t data, channel;
#     ifdef __CRTTDC3377_SINGLE_WORD
      //{{{  single word
      if (value < 0) // should be & 0x8000 !=0 but value is signed !
       //{{{  error
       {
        std::cout <<"Error in reading ... data word for single numbers no data word !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      data = (value & 0x03FF);
      channel = (value & 0x7C00) >>10;
      //}}}
#     else
      //{{{  double word
      // data structure is 2*8 bit data, 1 bit edge polarity, 5 bit channel 

      // first word of double word
      data = (value & 0xFF) << 8;
      channel = (value & 0x7C00) >>10;
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#      ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#      endif
      // second word of double word
      data += (value & 0xFF);
      if (channel != ((value & 0x7C00)>>10))
       //{{{  error
       {
        std::cout <<"Error in reading ... channel numbers do not agree !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      //}}}
#     endif
      if (outChannels[channel]<1)
       //{{{  store data
       { 
        outChannels[channel]=data;
        count++;
       }
       //}}}
     }
     //}}}
    Query(0,&value);
    Clear(CrtTdc3377Board::F_TDC3377_LAM);
    return count;
   }
  //}}}
  //{{{  ReadModule (with limits)
   Int_t CrtTdc3377Board::ReadModuleAndClear(Int_t *outChannels, Int_t inLowerLimit, Int_t inUpperLimit) const
   {
    // reads all channels and clears the data afterwards.
    // returns at most one hit in each channel.
    // In case there are no hits inside the limits, reports the earliest hit
    // In case there are hits inside the limits, reports the earliest of the hits inside the limits

    if (inLowerLimit<=0) inLowerLimit=1; // to protect us from counting wrong
    
#  ifdef __CRTTDC3377_DEBUG
    // for debugging purposes 
    static int datastore[4000];
    static int fifo[4000];
    int datastorecounter=0;
#  endif

    memset(outChannels,0,32*sizeof(Int_t));
    if (fOk!=1) return -1;

#  if 0
    if (Test(CrtTdc3377Board::F_TDC3377_BUSY)==0)
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}
#  endif
    
    if (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)==1) 
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}

    Int_t value;
    if (Query(0,&value)==0)
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}
    Int_t count=0;
    while (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)!=1)
     //{{{  forever
     {
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#     ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#     endif
        
      Int_t data, channel;
#     ifdef __CRTTDC3377_SINGLE_WORD
      //{{{  single word
      if (value < 0) // should be & 0x8000 !=0 but value is signed !
       //{{{  error
       {
        std::cout <<"Error in reading ... data word for single numbers no data word !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      data = (value & 0x03FF);
      channel = (value & 0x7C00) >>10;
      //}}}
#     else
      //{{{  double word
      // data structure is 2*8 bit data, 1 bit edge polarity, 5 bit channel 

      // first word of double word
      data = (value & 0xFF) << 8;
      channel = (value & 0x7C00) >>10;
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#      ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#      endif
      // second word of double word
      data += (value & 0xFF);
      if (channel != ((value & 0x7C00)>>10))
       //{{{  error
       {
        std::cout <<"Error in reading ... channel numbers do not agree !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      //}}}
#     endif
      if ((outChannels[channel]>=inLowerLimit)&&(outChannels[channel]<=inUpperLimit))
       //{{{  we already have a hit inside the limits, use the lower one
       { 
        if ((data<outChannels[channel])&&(data>=inLowerLimit))
         //{{{  store data
         { 
          outChannels[channel]=data;
         }
         //}}}
       }
       //}}}
      else if ((outChannels[channel]==0)&&(data>0))
       //{{{  we do not yet have a hit
       { 
        outChannels[channel]=data;
        count++;
       }
       //}}}
      else if (data<outChannels[channel])
       //{{{  we have a hit outside the limits, then store the earlier one
       { 
        outChannels[channel]=data;
       }
       //}}}
     }
     //}}}
    Query(0,&value);
    Clear(CrtTdc3377Board::F_TDC3377_LAM);
    return count;
   }
  //}}}
  //{{{  ReadModuleAllHits
   Int_t CrtTdc3377Board::ReadModuleAllHitsAndClear(Int_t *outChannels) const
   {
    // reads all hits on all channels and clears the data afterwards.
    // The array given has to have the size 
    // MAX_HITS * MAX_CHANNELS = 16 * 32 = 512,
    // the data will be ordered: hit_in_channel * 32 + channel_no
    
    Int_t i=0, value;
    Int_t currentnum[32];
    while (i<32*16)
     {
      outChannels[i++]=0;
     }
    i=0;
    while (i<32)
     {
      currentnum[i++]=0;
     }

    if (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)==1) 
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}

    if (Query(0,&value)==0)
     //{{{  return, no data
     { 
      Clear(CrtTdc3377Board::F_TDC3377_LAM);
      return 0;
     }
     //}}}

    Int_t count=0;
    while (Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG)!=1)
     //{{{  forever
     {
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#     ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#     endif
        
      Int_t data, channel;
#     ifdef __CRTTDC3377_SINGLE_WORD
      //{{{  single word
      if (value < 0) // should be & 0x8000 !=0 but value is signed !
       //{{{  error
       {
        std::cout <<"Error in reading ... data word for single numbers no data word !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      data = (value & 0x03FF);
      channel = (value & 0x7C00) >>10;
      //}}}
#     else
      //{{{  double work
      // data structure is 2*8 bit data, 1 bit edge polarity, 5 bit channel 

      // first word of double word
      data = (value & 0xFF) << 8;
      channel = (value & 0x7C00) >>10;
      if (Query(0,&value)==0)
       //{{{  handle no data case
       {
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return count;
       }
       //}}}
#      ifdef __CRTTDC3377_DEBUG
      if (datastorecounter<4000)
       //{{{  store all data
       { 
        datastore[datastorecounter]=value;
        fifo[datastorecounter]= Test(CrtTdc3377Board::F_TDC3377_FIFO_TAG);
        datastorecounter++;
       }
       //}}}
#      endif
      // second word of double word
      data += (value & 0xFF);
      if (channel != ((value & 0x7C00)>>10))
       //{{{  error
       {
        std::cout <<"Error in reading ... channel numbers do not agree !"<<std::endl;
#       ifdef __CRTTDC3377_DEBUG
        std::cout <<"Dumping all data ("<<datastorecounter<<" words)"<<std::endl;
        Int_t i=0;
        while (i<datastorecounter)
         {
          std::cout<<i<<" "<<hex<<datastore[i]<<" fifo = "<<fifo[i]<<std::endl;
          i++;
         }
        std::cout<<dec<<std::endl;
#       endif
        Clear(CrtTdc3377Board::F_TDC3377_LAM);
        return 0;
       }
       //}}}
      //}}}
#     endif
      if (currentnum[channel]<16)
       //{{{  store data
       { 
            // if (currentnum[channel]>0)
            //   if (outChannels[(currentnum[channel]-1)*32+channel]==data)
            //     continue;  // suppress multiple hits at same time
        outChannels[currentnum[channel]*32+channel]=data;
        currentnum[channel]++;
        count++;
       }
       //}}}
     }
     //}}}
    return count;
   }
  //}}}
  //{{{  GetNumberOfChannels
   Int_t CrtTdc3377Board::GetNumberOfChannels() const
   {
    return 32;
   }
  //}}}
 }
 
ClassImp(CRT::CrtTdc3377Board) //LeCroy 3377 TDC module driver

#endif


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.