CAENcard_767.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 #include <config.h>
00019 #include "CAENcard_767.h"
00020 
00021 
00022 
00023 #include <string>
00024 #include <Iostream.h>
00025 #include <CVMEInterface.h>
00026 
00027 #ifdef HAVE_STD_NAMESPACE
00028 using namespace std;
00029 #endif
00030 
00031 
00032 
00055 CAENcard_767::CAENcard_767(int slotNum, int crateNum,
00056                            bool fisGeo, unsigned long nBase) :
00057   slot(0), 
00058   m_pSpace(0)
00059   
00060 {
00061   if(slotInit(slotNum, crateNum, fisGeo, nBase) < 0) {
00062     throw string("CAENcard_767 construction failed!");
00063   }
00064 
00065 };
00066 
00078 CAENcard_767::CAENcard_767(const CAENcard_767& card) :
00079   slot(card.slot),
00080   m_pSpace(card.m_pSpace)
00081 {
00082 
00083 };
00084 
00093 CAENcard_767& 
00094 CAENcard_767::operator=(const CAENcard_767& card)
00095 {
00096   if(this != &card) {
00097     slot     = card.slot;
00098     m_pSpace = card.m_pSpace;
00099   }
00100   return *this;
00101 
00102 };
00103 
00125 int CAENcard_767::slotInit(int slotNum, int crateNum, 
00126                            bool fisGeo, unsigned long nBase)
00127 {
00128 
00129   //ensure that the slot and crate specified stay within bounds
00130 
00131   
00132   slot = slotNum;
00133 
00134 
00135   if((slot > VME_CRATE_SIZE) || (slot <= 0))
00136   {
00137     perror("Invalid slot number specified to slotInit(). ");
00138     return(-1);
00139   }
00140 
00141 
00142 
00143   // Create the VME module... this may be a GEO or an extended address
00144   // modifier range, depending on the base parameter.
00145 
00146   CVmeModule::Space space;
00147   unsigned long     base;
00148   
00149   // Based on the geo flag, figure out which space, and what the base is.
00150 
00151   if (fisGeo) {
00152     space = CAEN_GEO24;
00153     base  = slot << 19;
00154   }
00155   else {
00156     space = CAEN_A32D16;
00157     base  = nBase;
00158   }
00159 
00160   try {
00161     m_pSpace = new CVmeModule(space, base, CAEN_767_CARD_MMAP_LEN, crateNum);
00162   } 
00163   catch (string& msg) {
00164     cerr << "Could not map crate: " << crateNum << " slot: " << slot
00165          << " : " << msg << endl;
00166     return(-6);  
00167   }
00168    
00169 
00170 
00171   if(  !( (0x0040e6 == mfgId())                   &&
00172           (767    == cardType())                  &&
00173           (((short int)slot ==  (0x001F & m_pSpace->peekw(CAEN_767_ADDR_GEO))) ||
00174            !fisGeo))) {
00175 
00176       printf( "\n767 Card %d is not inserted or is of an incompatable type!\n", slotNum);
00177       printf("  One of the following tests has failed\n");
00178       printf("    0x0040e6 = 0x%6.6X\n", mfgId());
00179       printf("    767    == %d\n",  cardType());
00180       printf("    0x%4.4X == 0x%4.4X & 0x001F\n", slot,
00181                                           m_pSpace->peekw(CAEN_767_ADDR_GEO));
00182 
00183       delete m_pSpace;
00184       m_pSpace = NULL;
00185       return(-7);
00186   }
00187   // If the card is not being accessed geographically we program the slot:
00188 
00189   reset();
00190 
00191 
00192   if(!fisGeo) {
00193      m_pSpace->pokew(slot,CAEN_767_ADDR_GEO);
00194   }
00195 
00196   //disable the auto load of the user configuration at the next reset
00197 
00198   if(  ( writeOpcode(0x1900, 1000000) < 0 ) || ( opcodeWait(1000000) < 0 )  )
00199   {
00200     delete m_pSpace;
00201     m_pSpace = NULL;
00202     return(-10);
00203   }
00204 
00205   // end of slot initialization, begin address initialization.. This is only needed
00206   // if access is geographical.... as otherwise we're already mapped the way we
00207   // want to be!
00208 
00209   if(fisGeo) {
00210     m_pSpace->pokew(slot, CAEN_767_ADDR_32); // Set the new module address...
00211     m_pSpace->pokew(0,    CAEN_767_ADDR_24);
00212     m_pSpace->pokew(1<<4, CAEN_767_BIT_SET); // Enable address relocation.
00213 
00214     delete m_pSpace;
00215     m_pSpace = NULL;
00216     try {
00217       m_pSpace = new CVmeModule(CAEN_A32D16, slot << 24,
00218                                 CAEN_767_CARD_MMAP_LEN, crateNum);
00219     }
00220     catch (string& msg) {
00221       cerr << "Unable to create relocated address for CAEN-767 " 
00222            << msg << endl;
00223       return -11;
00224     }
00225 
00226   }
00227 
00228 
00229 
00230   // load the default configuration (only problem is that it is "Stop Trigger 
00231   // Matching")
00232 
00233   if(cardType() == 767)   {
00234     if(  ( writeOpcode(0x1500, 1000000) < 0 ) || ( opcodeWait(1000000) < 0 )  )
00235     {
00236       delete m_pSpace;
00237       m_pSpace = NULL;
00238       return(-14);
00239     }
00240   }
00241   sleep(5);
00242 
00243   return(0);
00244 };
00245 
00250 CAENcard_767::~CAENcard_767()
00251 {
00252   m_pSpace->pokew(1 << 4, CAEN_767_BIT_CLEAR); // Turn off any relocation
00253   delete m_pSpace;
00254 };
00255 
00267 int CAENcard_767::readOpcode(unsigned short int *value, int maxRetry)
00268 {
00269   int i;  
00270   for( i = 0; i < maxRetry; ++i ) {
00271     if( m_pSpace->peekw(CAEN_767_OPCODE_STATUS) & (1 << 0) ) {
00272       //the "read okay" bit is set
00273       break;
00274     }
00275   }
00276   
00277   if( i >= maxRetry )  {
00278     //never broke the loop...
00279     return(-1);
00280   }
00281   
00282   //take the prescribed 10ms timeout before reading the value
00283   
00284   usleep(10000);
00285   
00286   //now read the register and return
00287   *value = m_pSpace->peekw(CAEN_767_OPCODE);
00288   return( i );
00289 }
00290 
00300 int 
00301 CAENcard_767::writeOpcode(unsigned short int value, int maxRetry)
00302 {
00303   int i = opcodeWait(maxRetry);
00304 
00305   if (i >= 0) {
00306     
00307     //take the prescribed 10ms timeout before reading the value
00308     
00309     usleep(10000);
00310     
00311     //now write the register and return
00312     
00313     m_pSpace->pokew(value, CAEN_767_OPCODE);
00314   }
00315   return( i );
00316 
00317 };
00327 int CAENcard_767::opcodeWait(int maxRetry)
00328 {
00329   int i;  
00330   for( i = 0; i < maxRetry; ++i ) {
00331     if( m_pSpace->peekw(CAEN_767_OPCODE_STATUS) & (1 << 1) ) {
00332       //the "write okay" bit is set
00333       break;
00334     }
00335   }
00336   
00337   if( i == maxRetry ) {
00338     //never broke the loop...
00339     return(-2);
00340   }
00341   
00342   //take the prescribed 10ms timeout before doing anything else
00343   
00344   usleep(10000);
00345   
00346   return( i );
00347   
00348 }
00349 
00354 int CAENcard_767::cardType()
00355 {
00356   return (( (int)m_pSpace->peekw(CAEN_767_BOARD_ID) << 24)   |
00357           ( (int)m_pSpace->peekw(CAEN_767_BOARD_ID+2) << 16) |
00358           ( (int)m_pSpace->peekw(CAEN_767_BOARD_ID+4) << 8)  |
00359           ( (int)m_pSpace->peekw(CAEN_767_BOARD_ID+6)));
00360 };
00361 
00365 void CAENcard_767::clearData()
00366 {
00367   m_pSpace->pokew(1, CAEN_767_CLEAR);
00368 
00369 };
00370 
00371 
00372 void CAENcard_767::reset()
00373 {
00374   m_pSpace->pokew(1, CAEN_767_SS_RESET);
00375   sleep(2);
00376 
00377 };
00378 
00390 int CAENcard_767::dataPresent()
00391 {
00392 
00393   unsigned short s1 = m_pSpace->peekw(CAEN_767_STATUS_1);
00394   
00395   return ((s1 & 5) == 1 );
00396 
00397 };
00398 
00413 int CAENcard_767::readEvent(void* buf)
00414 {
00415   int temp, n = dataPresent();
00416   if(n > 0) {
00417     n = 0;
00418     // read until it hits an invalid datum (should there be an option to stop at EOB?)
00419     temp = m_pSpace->peekl(0);
00420     while( (temp & CAEN_767_DATUM_TYPE) != CAEN_767_INVALID )  {
00421       *(((int*)buf) + n) = temp;
00422       ++n;
00423       temp = m_pSpace->peekl(0);
00424     }
00425     n *= 4;  //convert the number of integers to the number of bytes
00426   }
00427   
00428   return(n);
00429 };
00430 
00446 int CAENcard_767::readEvent(DAQWordBuffer& wbuf, int offset)
00447 {
00448   int n = dataPresent();
00449   union{                        // Assume little endian longword order.
00450     int dword;
00451     struct{
00452       short int low;
00453       short int high;
00454     } word;
00455   } temp;
00456 
00457   if(n > 0)  {
00458     n = 0;
00459     // read until it hits an invalid datum (should there be an option to stop at EOB?)
00460     temp.dword = m_pSpace->peekl(0);
00461     
00462     while( (temp.dword & CAEN_767_DATUM_TYPE) != CAEN_767_FOOTER ) {
00463       wbuf[offset] = temp.word.high;
00464       wbuf[offset+1] = temp.word.low;
00465       ++n;
00466       temp.dword = m_pSpace->peekl(0);
00467     }
00468     if( (temp.dword & CAEN_767_DATUM_TYPE) == CAEN_767_FOOTER ) {
00469       wbuf[offset] = temp.word.high;
00470       wbuf[offset + 1] = temp.word.low;
00471       ++n;
00472     }
00473     
00474     n *= 2;
00475   }
00476   return(n);
00477 };
00478 
00494 int CAENcard_767::readEvent(DAQWordBufferPtr& wp)
00495 {
00496   int n = dataPresent();
00497   union{
00498     int dword;
00499     struct{
00500       short int low;
00501       short int high;
00502     } word;
00503   } temp;
00504 
00505   if(n > 0)
00506   {
00507     n = 0;
00508     temp.dword = m_pSpace->peekl(0);
00509     while( (temp.dword & CAEN_767_DATUM_TYPE) != CAEN_767_INVALID )
00510     {
00511       *wp = temp.word.high;
00512       wp++;
00513       *wp = temp.word.low;
00514       wp++;
00515       ++n;
00516       temp.dword = m_pSpace->peekl(0);
00517     }
00518 
00519     n *= 2;
00520   }
00521   return(n);
00522 };
00523 
00539 int CAENcard_767::readEvent(DAQDWordBuffer& dwbuf, int offset)
00540 {
00541   int temp, n = dataPresent();
00542   if(n > 0)
00543   {
00544     n = 0;
00545     temp = m_pSpace->peekl(0);
00546     while( (temp & CAEN_767_DATUM_TYPE) != CAEN_767_INVALID )
00547     {
00548       dwbuf[offset + n] = temp;
00549       ++n;
00550       temp = m_pSpace->peekl(0);
00551     }
00552   }
00553   return(n);
00554 };
00555 
00572 int CAENcard_767::readEvent(DAQDWordBufferPtr& dwp)
00573 {
00574   int temp, n = dataPresent();
00575   if(n > 0)
00576   {
00577     n = 0;
00578     temp = m_pSpace->peekl(0);
00579     while( (temp & CAEN_767_DATUM_TYPE) != CAEN_767_INVALID )
00580     {
00581       *dwp = temp;
00582       dwp++;
00583       ++n;
00584       temp = m_pSpace->peekl(0);
00585     }
00586   }
00587   return(n);
00588 };
00589 
00590 
00596 int
00597 CAENcard_767::tempSetup()
00598 {
00599   //set to common start mode ("Start Gating")
00600   // -- saves all conversions while the start signal is high.  the trigger signal is unused
00601   if( writeOpcode(0x1200, 1000000) < 0 )
00602     {
00603       return(-1);
00604     }
00605   
00606   //set data-ready mode to be event-ready
00607   if( writeOpcode(0x7000, 1000000) < 0 )
00608     {
00609       return(-2);
00610     }
00611   
00612   //enable subtraction of start time for start gating mode
00613   if( writeOpcode(0x4300, 1000000) < 0)
00614     {
00615       return(-3);
00616     }
00617   opcodeWait(1000000);
00618   
00619   return(0);
00620 }
00626 int 
00627 CAENcard_767::SetRisingEdgeStart()
00628 {
00629   if(writeOpcode(0x6400, 1000000) < 0) {
00630     return -1;
00631   }
00632   opcodeWait(1000000);
00633   return 0;
00634 }
00640 int
00641 CAENcard_767::SetFallingEdgeStart()
00642 {
00643   if(writeOpcode(0x6500, 100000) < 0) {
00644     return -1;
00645   }
00646   opcodeWait(100000);
00647   return 0;
00648 }
00652 int
00653 CAENcard_767::SetRisingEdgeAll()
00654 {
00655   if(writeOpcode(0x6000, 1000000) < 0) {
00656     return -1;
00657   }
00658   opcodeWait(1000000);
00659   return 0;
00660 }
00664 int
00665 CAENcard_767::SetFallingEdgeAll()
00666 {
00667   if(writeOpcode(0x6100, 1000000) < 0) {
00668     return -1;
00669   }
00670   opcodeWait(1000000);
00671   return 0;
00672 }
00677 int
00678 CAENcard_767::getStartEdge() {
00679   unsigned short edges[3];
00680   int stat = readEdgeConfiguration(edges);
00681   if (stat < 0) {
00682     return stat;
00683   }
00684   return edges[2];
00685 }
00689 int
00690 CAENcard_767::getEdgeEven()
00691 {
00692   unsigned short edges[3];
00693   int stat = readEdgeConfiguration(edges);
00694   if (stat < 0) {
00695     return stat;
00696   }
00697   return edges[0];
00698 }
00702 int 
00703 CAENcard_767::getEdgeOdd()
00704 {
00705   unsigned short edges[3];
00706   int stat = readEdgeConfiguration(edges);
00707   if (stat < 0) {
00708     return stat;
00709   }
00710   return edges[1];  
00711 }
00715 unsigned short CAENcard_767::getSr2()
00716 {
00717   return m_pSpace->peekw(CAEN_767_STATUS_2);
00718 }
00722 int
00723 CAENcard_767::mfgId()
00724 {
00725   return ((m_pSpace->peekw(CAEN_767_MANUFACT_ID) <<   16)  |
00726           (m_pSpace->peekw(CAEN_767_MANUFACT_ID+2) << 8)  |
00727           (m_pSpace->peekw(CAEN_767_MANUFACT_ID+4)));
00728 }
00729 
00730 
00734 int
00735 CAENcard_767::readEdgeConfiguration(unsigned short* values)
00736 {
00737   if (writeOpcode(0x6700, 10000) < 0) {
00738     return -1;
00739   }
00740   opcodeWait(1000000);
00741   if (readOpcode(values, 1000) < 0) { // Even channels..
00742     return -2;
00743   }
00744   *values &= CAEN_767_EDGE_BOTH;
00745   values++;
00746   if (readOpcode(values, 1000) < 0) { // Odd channels..
00747     return -3;
00748   } 
00749   *values &= CAEN_767_EDGE_BOTH;
00750   values++;
00751   if (readOpcode(values, 1000) < 0) { // Start channel...
00752     return -4;
00753   }
00754   *values &= CAEN_767_EDGE_BOTH;
00755   return 0;
00756 }

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