CCAENChain.cpp

Go to the documentation of this file.
00001 /*
00002     This software is Copyright by the Board of Trustees of Michigan
00003     State University (c) Copyright 2005.
00004 
00005     You may use this software under the terms of the GNU public license
00006     (GPL).  The terms of this license are described at:
00007 
00008      http://www.gnu.org/licenses/gpl.txt
00009 
00010      Author:
00011              Ron Fox
00012              NSCL
00013              Michigan State University
00014              East Lansing, MI 48824-1321
00015 */
00016 
00017 
00018 #define DMA_THRESHOLD 34*20*4   // Don't allow it to go DMA.
00019 
00020 /*
00021   Revision history:
00022   $Log$
00023   Revision 8.2  2005/06/24 11:30:36  ron-fox
00024   Bring the entire world onto the 8.2 line
00025 
00026   Revision 4.3  2004/12/07 15:20:21  ron-fox
00027   - Fix some CVS errors with the wiener driver.
00028   - Re create the autotools based build for the wiener driver stuff.
00029   - Actually check that we can compile the stuff selecting the wiener
00030     vme device
00031 
00032   Revision 4.2  2004/11/16 15:24:48  ron-fox
00033   - Port to the gnu 3.x compiler set.
00034   - Integrate buid of tests.
00035   - Integrate build of docos.
00036 
00037   Revision 1.2  2004/11/16 15:23:28  ron-fox
00038   - Port -> gcc/g++ 3.x
00039   - Support integrated test building.
00040   - Support integrated doxygen docu7mentation building.
00041 
00042   Revision 1.1  2003/12/03 18:45:45  ron-fox
00043   Update 767 documentation
00044 
00045   Revision 1.2  2003/09/19 19:52:45  ron-fox
00046   This is probably debugged.  Need to see what CAEN says about data corruption .
00047 
00048   Revision 1.1  2003/09/16 12:16:24  ron-fox
00049   Added support for CBLT readout of CAEN 32 channel adcs.  Note for SBS/bit3 the driver must be patched to support early termination of block transfers.
00050 
00051 */
00052 #include <config.h>
00053 #include "CCAENChain.h"
00054 #include "CAENcard.h"
00055 #include <CVMEInterface.h>
00056 #ifdef HAVE_SBSVME_INTERFACE
00057 #include <SBSBit3API.h>
00058 #endif
00059 
00060 #include <stdio.h>
00061 
00062 #ifdef HAVE_STD_NAMESPACE
00063 using namespace std;
00064 #endif
00065 
00066 
00067 static const int QualifyingFirmware(0x0904);
00068 
00069 
00070 static int fwMajor(int firmware) 
00071 {
00072   return (firmware >> 8) & 0xff;
00073 }
00074 static int fwMinor(int firmware) 
00075 {
00076   return firmware & 0xff;
00077 }
00113 CCAENChain::CCAENChain(int nFirstSlot, int nLastSlot,
00114                        vector<unsigned long>& vBases,
00115                        int nCrate, bool geo) throw (string)
00116       : m_nCBLTAddress(0),
00117         m_nCrate(nCrate),
00118         m_pHandle(0),
00119         m_nMaxBytes(0)
00120 {
00121 
00122   // Require legitimate length of chain:
00123 
00124   int nModules = (nLastSlot - nFirstSlot + 1);
00125   if(nModules < 2) {
00126     throw string("Chains must have at least two modules!!");
00127   }
00128   // If not geo, require sufficient bases:
00129 
00130   if(!geo & (vBases.size() != nModules)) {
00131     throw string("Insufficient module base addresses in CAENChain");
00132   }
00133   
00134 
00135   // Create the modules in the chain.
00136   // 
00137   int i = 0;
00138   try {
00139     for(int slot = nFirstSlot; slot <= nLastSlot; slot++, i++) {
00140       m_vCards.push_back(new CAENcard(slot, nCrate, geo,
00141                                       geo ?  0 : vBases[i]));
00142     }
00143   } 
00144   catch(...) {                  // On any exception:
00145     FreeModules();              // Free the modules already created
00146     throw;                      // and rethrow.
00147   }
00148 
00149   // All of the modules in the chain must be at firmware 9.04 or higher
00150   // at least.  This corresponds to a firmware value of
00151   // 0x0904 or larger.
00152 
00153   try {
00154     for (int slot = 0; slot < m_vCards.size(); slot++) {
00155       if (m_vCards[slot]->getFirmware() < QualifyingFirmware) {
00156         unsigned long base    = m_vCards[slot]->getBase();
00157         int           fw      = m_vCards[slot]->getFirmware();
00158         int           major   = fwMajor(fw);
00159         int           minor   = fwMinor(fw);
00160         int           qmajor  = fwMajor(QualifyingFirmware);
00161         int           qminor  = fwMinor(QualifyingFirmware);
00162         char errorMessage[1000];
00163         sprintf(errorMessage,
00164                 "All modules in the chain must have firmware rev at least %d.%d, the module base address 0x%08x (slot %d) has firmware rev %d.%d",
00165                 qmajor, qminor, base, m_vCards[slot]->getSlot(), major, minor);
00166         throw(string(errorMessage));
00167 
00168       }
00169     }
00170   }
00171   catch (...) {
00172     FreeModules();
00173     throw;
00174   }
00175 
00176   //  The base address of the chain is essentially the first
00177   //  slot number (shifted left by 16 bits to fall into the 
00178   //  range of address bits covered by the MCST/CBLT bits in the
00179   //  module's MCST/CBLT register.
00180   //
00181 
00182   m_nCBLTAddress = nFirstSlot << 24;
00183   for(i = 0; i < nModules; i++) {
00184     CAENcard::ChainMember where(CAENcard::IntermediateInChain);
00185     if(i == 0) where = CAENcard::FirstInChain;
00186     if(i == (nModules - 1))  where = CAENcard::LastInChain;
00187     m_vCards[i]->SetCBLTChainMembership(nFirstSlot, where);
00188   }
00189 
00190   // Calculate the  number of bytes that can be read:
00191   // In cblt seems like a module returns
00192   //  header data trailer invalid 
00193   //   Data can be 32 longs,
00194   //   header, trailer and invalid are both a single long.
00195 
00196   m_nMaxBytes = (nModules * 35 + 1) * sizeof(long);
00197 
00198   // The very last thing to do is open the VME crate on
00199   // CBLT addressing so that we can do a read(2) to read an event:
00200 
00201   try {
00202     m_pHandle = CVMEInterface::Open(CVMEInterface::CBLT, nCrate);
00203 #ifdef HAVE_SBSVME_INTERFACE
00204     CSBSBit3VmeInterface::SetDMABlockTransfer(m_pHandle, true);
00205     CSBSBit3VmeInterface::SetDMAThreshold(m_pHandle, DMA_THRESHOLD);
00206 #endif
00207   }
00208   catch (...) {
00209     FreeModules();
00210     throw;
00211   }
00212                                    
00213   
00214 }
00220 CCAENChain::~CCAENChain() 
00221 {
00222   FreeModules();
00223   CVMEInterface::Close(m_pHandle);
00224 }
00235 CAENcard*
00236 CCAENChain::operator[](int index) throw (CRangeError)
00237 {
00238   if( (index >= 0) && (index < m_vCards.size())) {
00239     return m_vCards[index];
00240   }
00241   else {
00242     throw CRangeError(0, m_vCards.size(), index,
00243                       "Selecting a CAENcard from a chain");
00244   }
00245 
00246 }
00281 int
00282 CCAENChain::ReadEvent(void* pBuffer)
00283 {
00284   int nCards = m_vCards.size();
00285   int nRead = 0;
00286   try {
00287     nRead = CVMEInterface::Read(m_pHandle,
00288                         m_nCBLTAddress,
00289                         pBuffer, m_nMaxBytes);
00290   }
00291   catch (... ) {                //  Try to reset the adapter on error.
00292     // See if reopening fixes this (ugghhh).
00293     CVMEInterface::Close(m_pHandle);
00294     m_pHandle = CVMEInterface::Open(CVMEInterface::CBLT, m_nCrate);
00295 #ifdef HAVE_SBSVME_INTERFACE
00296     CSBSBit3VmeInterface::SetDMABlockTransfer(m_pHandle, true);
00297     CSBSBit3VmeInterface::SetDMAThreshold(m_pHandle, DMA_THRESHOLD);    
00298 #endif
00299     throw;                      // But re-report the error.
00300   }
00301 
00302   return nRead/sizeof(unsigned short);
00303 }
00307 void
00308 CCAENChain::ClearData()
00309 {
00310   int ncards = m_vCards.size();
00311   for(int i = 0; i < ncards; i++) {
00312     m_vCards[i]->clearData();
00313   }
00314 }
00315 
00323 void
00324 CCAENChain::FreeModules()
00325 {
00326   for(int i=0; i < m_vCards.size(); i++ ) {
00327     delete m_vCards[i];
00328   }
00329   m_vCards.erase(m_vCards.begin(), m_vCards.end());
00330 }
00331 
00350 void 
00351 CCAENChain::lastModuleEmptyEnable() 
00352 {
00353 
00354   CAENcard* pCard = lastCard();
00355   pCard->emptyEnable();
00356 }
00357 
00364 void 
00365 CCAENChain::lastModuleEmptyDisable()
00366 {
00367   CAENcard*  pCard = lastCard();
00368   pCard->emptyDisable();
00369 }
00370 
00371 /*
00372   Utility to return the last card in the chain (DRY).
00373 */
00374 CAENcard*
00375 CCAENChain::lastCard()
00376 {
00377   // Get the pointer to the last module:
00378 
00379   CAENcard* pCard = m_vCards.back();
00380   return pCard;
00381 }

Generated on Wed Sep 17 08:38:09 2008 for NSCL Device support. by  doxygen 1.5.1