CCAENV1x90.cpp

Go to the documentation of this file.
00001 /*
00002   Implementation of the CCAENV1x90 class.
00003   For more information about this class, see the associated header:
00004   CCAENV1x90.h
00005 */
00006 
00007 // Headers etc.
00008 
00009 #include <config.h>
00010 
00011 #include "CCAENV1x90.h"
00012 #include "CCAENV1x90Registers.h"
00013 #include "CCAENV1x90Data.h"
00014 #include "CCAENV1x90Opcodes.h"
00015 
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <unistd.h>
00019 
00020 #include <string>
00021 #include <vector>
00022 
00023 
00024 
00025 // Namespace imports:
00026 
00027 #ifdef HAVE_STD_NAMESPACE
00028 using namespace std;
00029 #endif
00030 using namespace DesignByContract;
00031 using namespace CCAENV1x90Registers;
00032 using namespace CCAENV1x90Data;
00033 
00034 // Static class level data.  This data is present in order
00035 // To allow us to wrap some bit definitions into a name-space
00036 // like scope via class inclusion.  These definitions are not
00037 // suitable for the registers nor the data namespaces.
00038 //
00039 
00040 // Chip error bits:
00041 
00042 const unsigned short CCAENV1x90::ERR_VERNIER    (0x0001);
00043 const unsigned short CCAENV1x90::ERR_COARSE     (0x0002);
00044 const unsigned short CCAENV1x90::ERR_SELECT     (0x0004);
00045 const unsigned short CCAENV1x90::ERR_L1PARITY   (0x0008);
00046 const unsigned short CCAENV1x90::ERR_TFIFOPARITY(0x0010);
00047 const unsigned short CCAENV1x90::ERR_MATCHERROR (0x0020);
00048 const unsigned short CCAENV1x90::ERR_RFIFOPARITY(0x0040);
00049 const unsigned short CCAENV1x90::ERR_RDOSTATE   (0x0080);
00050 const unsigned short CCAENV1x90::ERR_SUPPARITY  (0x0100);
00051 const unsigned short CCAENV1x90::ERR_CTLPARITY  (0x0200);
00052 const unsigned short CCAENV1x90::ERR_JTAGPARITY (0x0400);
00053 
00054 // Tap contact bits (used in calibrate delay line).
00055 // These bits are shifted into position appropriately
00056 // to control fine adjustments of the RC delay line.
00057 
00058 const unsigned short CCAENV1x90::TAP_CONTACT1(4);
00059 const unsigned short CCAENV1x90::TAP_CONTACT2(2);
00060 const unsigned short CCAENV1x90::TAP_CONTACT3(1);
00061 
00062 //  Below are constants that are not worth member status
00063 //  but also should not be used as 'magic numbers'.
00064 
00065 static const unsigned int MINMATCHWIDTH(1);
00066 static const unsigned int MAXMATCHWIDTH(0xfff);
00067 static const unsigned int MATCHMASK(0xfff);
00068 
00069 static const int          MINWINDOWOFFSET(-2048);
00070 static const int          MAXWINDOWOFFSET(40);
00071 static const int          WINDOWOFFSETMASK(0xfff);
00072 
00073 static const unsigned int MINEXTRAMARGIN(0);
00074 static const unsigned int MAXEXTRAMARGIN(2047);
00075 static const unsigned int EXTRAMARGINMASK(0xfff);
00076 
00077 static const unsigned int MINREJECTMARGIN(0);
00078 static const unsigned int MAXREJECTMARGIN(2047);
00079 static const unsigned int REJECTMARGINMASK(0xfff);
00080 
00081 static const unsigned int EDGEDETECTIONMASK(3);
00082 
00083 static const unsigned int EDGERESOLUTIONMASK(3);
00084 static const unsigned int LERESOLUTIONMASK(7);
00085 
00086 static const unsigned int PWRESOLUTIONRSHIFT(8);
00087 static const unsigned int PWRESOLUTIONMASK(0xff00);
00088 
00089 static const unsigned int TRUEBIT(1); // TRUE for bools from sequencer.
00090 
00091 static const unsigned int COARSEMAX(0x7ff);
00092 static const unsigned int COARSEMASK(0x7ff);
00093 
00094 static const unsigned int VERNIERMAX(0x1f);
00095 static const unsigned int VERNIERMASK(0x1f);
00096 
00097 static const unsigned int CHANOFFSETMAX(0xff);
00098 static const unsigned int CHANOFFSETMASK(0xff);
00099 
00100 static const unsigned int TAPCONTACTMASK(0x7);
00101 static const unsigned int TAPCONTACTRSHIFT(3);
00102 
00103 static const unsigned int  MAXTESTVALUE(0x7fffff);
00104 
00105 static const unsigned int MAXGEO(0x1f);
00106 static const unsigned int GEOMASK(0x1f);
00107 
00108 static const unsigned long RESET_DELAY(1000);
00109 
00110 // Utility inline functions:
00111 
00113 
00114 static inline unsigned long OffsetW(unsigned long nByteOffset) 
00115 {
00116   return nByteOffset/sizeof(short);
00117 }
00119 
00120 static inline unsigned long OffsetL(unsigned long nByteOffset)
00121 {
00122   return nByteOffset/sizeof(long);
00123 }
00124 
00126 //   string:
00127 
00128 template <class T>
00129 static inline string FormatValue(const char* pFormatString, T value)
00130 {
00131   int nformatsize = strlen(pFormatString);
00132   char*  message = new char[nformatsize+100];
00133   sprintf(message, pFormatString, value);
00134   string m(message);
00135   delete []message;
00136   return m;
00137 
00138 }
00139 
00141 
00142 static unsigned short 
00143 inline HI(unsigned int nValue) 
00144 {
00145   return static_cast<unsigned short>((nValue >> 16) & 0xffff);
00146 }
00147 
00149 
00150 static unsigned short
00151 inline LO(unsigned int nValue)
00152 {
00153   return static_cast<unsigned short>(nValue & 0xffff);
00154 }
00155 
00156 
00158 
00197 CCAENV1x90::CCAENV1x90(unsigned int nSlot,
00198                        unsigned int nCrate,
00199                        unsigned long nBase) :
00200   m_nBase(nBase),
00201   m_nCrate(nCrate),
00202   m_nSlot(nSlot),
00203   m_pRegisters(CVmeModule::a32d32, nBase, RegisterSize, nCrate)
00204 {
00205   // Check preconditions:
00206 
00207   REQUIRE(((nSlot  >= 1)  && (nSlot <=20)), "Slot out of range");
00208   REQUIRE(((nCrate >= 0)  && (nCrate <= 7)), "Crate out of range");
00209 
00210   // Initializers create the module object for the 
00211   // control registers and data buffer.
00212   // we need to make one for the config prom so that we can
00213   // validate the module.
00214 
00215   CVmeModule pRom(CVmeModule::a32d32, 
00216                   m_nBase+ConfigRom, 
00217                   ConfigRomSize,
00218                   m_nCrate);
00219 
00220   // The configuration PROM can tell us if this is a valid board:
00221 
00222   ENSURE(ValidBoard(pRom), 
00223          "Board is not a valid CAEN V1x90 module");
00224 
00225   // Since the board is valid, set up the member variables
00226   // from the board properties as described in the config rom
00227   // and the various board registers:
00228 
00229   BoardProperties(pRom);
00230 
00231 
00232   // Check postconditions for model etc.:
00233 
00234   ENSURE(((m_nModel == 1190) || (m_nModel == 1290)),
00235          "Model number is incorrect on postcondition check");
00236   ENSURE(((m_cVersion == 'A') || (m_cVersion == 'B') || 
00237           (m_cVersion == 'N')),
00238          "Version is not A,B, or N in postcondition check");
00239 
00240 
00241   // Everything is good. Set slot,  turn on the FIFO:
00242 
00243   Reset();
00244   
00245 }
00246 
00255 CCAENV1x90::~CCAENV1x90()
00256 {}
00257 
00258 
00270 bool 
00271 CCAENV1x90::isSetCR(unsigned short bit)
00272 {
00273   return ((ReadCR() & (1 << bit)) != 0);
00274 }
00281 void
00282 CCAENV1x90::Terminate()
00283 {
00284   BitSetCR(ControlRegister::NTERM_SW); // Enable software termination.
00285   BitSetCR(ControlRegister::NTERM); // And request termination.
00286 }
00294 void
00295 CCAENV1x90::Unterminate()
00296 {
00297   BitSetCR(ControlRegister::NTERM_SW); // Enable software termination ctl
00298   BitClearCR(ControlRegister::NTERM); // Request unterminated.
00299 }
00310 void 
00311 CCAENV1x90::TerminateWithSwitch()
00312 {
00313   BitClearCR(ControlRegister::NTERM_SW); // Turn off software termination ctl.
00314 }
00322 void
00323 CCAENV1x90::EnableTriggerTagTime()
00324 {
00325   BitSetCR(ControlRegister::NTRIGGER_TAG_ENABLE);
00326 }
00332 void
00333 CCAENV1x90::DisableTriggerTagTime()
00334 {
00335   BitClearCR(ControlRegister::NTRIGGER_TAG_ENABLE);
00336 }
00347 bool
00348 CCAENV1x90::DataReady()
00349 {
00350   return isSetSR(StatusRegister::NDATA_READY);
00351 }
00364 bool
00365 CCAENV1x90::AlmostFull()
00366 {
00367   return isSetSR(StatusRegister::NALM_FULL);
00368 }
00369 
00383 bool
00384 CCAENV1x90::isFull()
00385 {
00386   return isSetSR(StatusRegister::NFULL);
00387 }
00388 
00410 bool
00411 CCAENV1x90::isTriggerMatching()
00412 {
00413   return isSetSR(StatusRegister::NTRG_MATCH);
00414 }
00427 bool
00428 CCAENV1x90::isHeaderEnabled()
00429 {
00430   return isSetSR(StatusRegister::NHEADER_EN);
00431 }
00432 
00445 bool
00446 CCAENV1x90::isTerminated()
00447 {
00448   return isSetSR(StatusRegister::NTERM_ON);
00449 }
00471 bool
00472 CCAENV1x90::HadError(unsigned int nChip)
00473 {
00474   // Check preconditions.
00475 
00476   REQUIRE(nChip < m_nChipCount, "Illegal chip number for device");
00477   
00478   // Compute the chip bit.  There's a huge assumption
00479   // here that the chip error bits are contiguous.
00480   // The debug code below will check this:
00481 
00482   ENSURE(((1 << StatusRegister::NCHIP0_ERROR)     |
00483           (1 << (StatusRegister::NCHIP0_ERROR+1)) |
00484           (1 << (StatusRegister::NCHIP0_ERROR+2)) |
00485           (1 << (StatusRegister::NCHIP0_ERROR+3))) == 
00486                                       ((StatusRegister::CHIP0_ERROR) |
00487                                        (StatusRegister::CHIP1_ERROR) |
00488                                        (StatusRegister::CHIP2_ERROR) |
00489                                        (StatusRegister::CHIP3_ERROR)),
00490          "Chip error bits are not continguous in the register");
00491   unsigned int nChipBit = 1 << (StatusRegister::NCHIP0_ERROR + nChip);
00492 
00493   // Return true if the associated error bit is set:
00494 
00495   return isSetSR(nChipBit);
00496 
00497 }
00510 int
00511 CCAENV1x90::ReadResolution()
00512 {
00513   int Resmask = SR() & StatusRegister::RESOLUTIONMASK;
00514 
00515   if(Resmask == StatusRegister::RES_800ps) {
00516     return 800;
00517   }
00518   else if (Resmask == StatusRegister::RES_200ps) {
00519     return 200;
00520   }
00521   else if (Resmask == StatusRegister::RES_100ps) {
00522     return 100;
00523   }
00524   else if(Resmask ==  StatusRegister::RES_25ps) {
00525     m_fIsHiResMode = true;      // module in hi res mode.
00526     return 25;
00527   } 
00528   else {
00529     CHECK(0, "Unrecognized resolution code");
00530   }
00531 }
00532 
00543 bool
00544 CCAENV1x90::isPairMode()
00545 {
00546   // I'm going to do a bit more work than I probably need to
00547   // by not assuming the pair bit is meaningful when the
00548   // 1290 is in pair mode:
00549 
00550   if((m_nModel == 1290) && (ReadResolution() == 25)) {
00551     return false;               // 1290 in hi res.
00552   }
00553   return isSetSR(StatusRegister::NPAIR);
00554 }
00565 bool
00566 CCAENV1x90::WereTriggersLost()
00567 {
00568   return isSetSR(StatusRegister::NTRIGGERLOST);
00569 }
00593 void 
00594 CCAENV1x90::SetGeographicalID(unsigned short nSlot)
00595 {
00596   // Check preconditions:
00597 
00598 
00599   REQUIRE(nSlot <= MAXGEO, "Slot number too big.");
00600 
00601   // Program the geo register:
00602 
00603   m_pRegisters.pokew(nSlot, OffsetW(WVirtualSlot));
00604   
00605   // Ensure it stayed programmed:
00606 
00607   if (GetGeographicalID() != nSlot) {
00608     throw 
00609       string ("Attempt to set geo register of geo-recognizing module");
00610   }
00611 
00612 }
00613 
00622 unsigned short
00623 CCAENV1x90::GetGeographicalID()
00624 {
00625   unsigned short g = m_pRegisters.peekw(OffsetW(WVirtualSlot));
00626   g &= GEOMASK;
00627   return g;
00628 
00629 }
00633 void
00634 CCAENV1x90::Reset()
00635 {
00636   m_pRegisters.pokew(0, OffsetW(WReset));
00637   m_fTriggerMatching = isTriggerMatching();
00638   WaitMicroWrite();
00639 
00640 
00641   // Re-asssert the slot and fifo enable.
00642 
00643   SetGeographicalID(m_nSlot);
00644   BitSetCR(ControlRegister::NEVENT_FIFO_ENABLE);
00645 
00646 
00647 }
00657 void 
00658 CCAENV1x90::Clear()
00659 {
00660   m_pRegisters.pokew(0, OffsetW(WClear));
00661   m_fTriggerMatching = isTriggerMatching();
00662 }
00663 
00669 void
00670 CCAENV1x90::EventReset()
00671 {
00672   m_pRegisters.pokew(0, OffsetW(WEventReset));
00673   m_fTriggerMatching = isTriggerMatching();
00674 }
00675 
00682 void
00683 CCAENV1x90::Trigger()
00684 {
00685   m_pRegisters.pokew(0, OffsetW(WSWTrigger));
00686 }
00687 
00697 unsigned long
00698 CCAENV1x90::TriggerCount()
00699 {
00700   return m_pRegisters.peekl(OffsetL(LEventCounter));
00701 }
00702 
00710 unsigned short
00711 CCAENV1x90::EventCount()
00712 {
00713   return m_pRegisters.peekw(OffsetW(WEventStored));
00714 }
00715 
00730 void
00731 CCAENV1x90::SetAlmostFullLevel(unsigned int nWords)
00732 {
00733   // Ensure preconditions are met:
00734 
00735   REQUIRE(nWords > 0, "Number of words is too small");
00736   REQUIRE(nWords <= 32735, "Number of words too big");
00737 
00738     // program the register.
00739 
00740   m_pRegisters.pokew(static_cast<unsigned short>(nWords), 
00741                      OffsetW(WAlmostFullLevel));
00742 
00743 }
00744 
00755 unsigned short
00756 CCAENV1x90::GetAlmostFullLevel()
00757 {
00758   return m_pRegisters.peekw(OffsetW(WAlmostFullLevel));
00759 }
00760 
00783 void
00784 CCAENV1x90::DefineECLOutput(CCAENV1x90::ECLOutputSelect Signal)
00785 {
00786   // Verify the precondition:
00787 
00788   REQUIRE(((Signal == DATA_READY)   ||
00789          (Signal == FULL)         ||
00790          (Signal == ALMOST_FULL)  ||
00791          (Signal == ERROR)),
00792         "Signal parameter is invalid.");
00793 
00794 
00795   // Convert our enum to register bits.
00796 
00797   unsigned short value;
00798 
00799   switch (Signal) {
00800   case DATA_READY:
00801     value = OutputControl::DATA_READY;
00802     break;
00803   case FULL:
00804     value = OutputControl::FULL;
00805     break;
00806   case ALMOST_FULL:
00807     value = OutputControl::ALM_FULL;
00808     break;
00809   case ERROR:
00810     value = OutputControl::ERROR;
00811     break;
00812     
00813     // Default case is prevented by precondition.
00814   }
00815 
00816   m_pRegisters.pokew(value, OffsetW(WOutputControl));
00817 
00818 }
00837 CCAENV1x90::ECLOutputSelect
00838 CCAENV1x90::GetECLOutputDefinition()
00839 {
00840   unsigned short 
00841     value = m_pRegisters.peekw(OffsetW(WOutputControl)) &
00842                                            OutputControl::MASK;
00843 
00844   // Convert the register value to the enum... the default
00845   // of the case below is illegal:
00846 
00847   if(value == OutputControl::DATA_READY) {
00848     return DATA_READY;
00849   } 
00850   else if (value == OutputControl::FULL) {
00851     return FULL;
00852   } 
00853   else if (value == OutputControl::ALM_FULL) {
00854     return ALMOST_FULL;
00855   }
00856   else if (value ==  OutputControl::ERROR) {
00857     return ERROR;
00858   }
00859   else {
00860     ENSURE(0, "Illegal value from output control register");
00861   }
00862 
00863 }
00875 unsigned short
00876 CCAENV1x90::EventFIFOCount()
00877 {
00878   return m_pRegisters.peekw(OffsetW(WEventFIFOStored)) & 
00879                          EventFIFO::FIFOCOUNT_MASK;
00880 }
00894 unsigned short
00895 CCAENV1x90::FIFOEventNumber(unsigned long fifoentry)
00896 {
00897   return (fifoentry & EventFIFO::EVENTCOUNT_MASK) >>
00898                       EventFIFO::EVENTCOUNT_RSHIFT;
00899 }
00900 
00915 unsigned short
00916 CCAENV1x90::FIFOWordCount(unsigned long fifoentry)
00917 {
00918   return (fifoentry & EventFIFO::WORDCOUNT_MASK) >>
00919                       EventFIFO::WORDCOUNT_RSHIFT;
00920 }
00921 
00942 unsigned long
00943 CCAENV1x90::ReadEventFIFO()
00944 {
00945   // check preconditions.
00946 
00947   REQUIRE(isEventFIFOReady(), "Attempting to read empty FIFO");
00948 
00949   return m_pRegisters.peekl(OffsetL(LEventFIFO));
00950 }
00951 
00960 bool
00961 CCAENV1x90::isEventFIFOReady()
00962 {
00963   
00964   return ((m_pRegisters.peekw(OffsetW(WEventFIFOStatus)) &
00965            FIFOStatus::EVFIFODATA_READY) != 0);
00966 }
00967 
00977 bool
00978 CCAENV1x90::isEventFIFOFull()
00979 {
00980   return ((m_pRegisters.peekw(OffsetW(WEventFIFOStatus)) &
00981            FIFOStatus::EVFIFO_FULL) != 0);
00982 }
00983 
00984 
00986 
00993 void 
00994 CCAENV1x90::TriggerMatchMode()
00995 {
00996   m_fTriggerMatching = true;
00997   WriteMicro(CCAENV1x90Opcodes::TRG_MATCH);
00998   WaitMicroWrite();
00999 }
01000 
01004 void
01005 CCAENV1x90::ContinuousStorageMode()
01006 {
01007   m_fTriggerMatching = false;
01008   WriteMicro(CCAENV1x90Opcodes::CONT_STOR);
01009   WaitMicroWrite();
01010 
01011 }
01028 void
01029 CCAENV1x90::TransferUntilDone()
01030 {
01031   WriteMicro(CCAENV1x90Opcodes::SET_KEEP_TOKEN);
01032   WaitMicroWrite();
01033 
01034 }
01040 void
01041 CCAENV1x90::TransferOneAtATime()
01042 {
01043   WriteMicro(CCAENV1x90Opcodes::CLEAR_KEEP_TOKEN);
01044   WaitMicroWrite();
01045   
01046 }
01047 
01051 void
01052 CCAENV1x90::LoadDefaultConfig()
01053 {
01054   WriteMicro(CCAENV1x90Opcodes::LOAD_DEF_CONFIG);
01055   WaitMicroWrite();
01056 
01057 }
01078 void
01079 CCAENV1x90::SaveUserConfig()
01080 {
01081   WriteMicro(CCAENV1x90Opcodes::SAVE_USER_CONFIG);
01082   WaitMicroWrite();
01083   usleep(10000);                // Carlo says wait 10ms after this opcode.
01084 }
01091 void
01092 CCAENV1x90::LoadUserConfig()
01093 {
01094   WriteMicro(CCAENV1x90Opcodes::LOAD_USER_CONFIG);
01095   WaitMicroWrite();
01096 }
01104 void
01105 CCAENV1x90::AutoLoadUserConfig()
01106 {
01107   WriteMicro(CCAENV1x90Opcodes::AUTOLOAD_USER_CONFIG);
01108   WaitMicroWrite();
01109   usleep(10000);                // Carlo says wait 10ms after this opcode.
01110 
01111 }
01122 void
01123 CCAENV1x90::AutoLoadDefaultConfig()
01124 {
01125   WriteMicro(CCAENV1x90Opcodes::AUTOLOAD_DEF_CONFIG);
01126   WaitMicroWrite();
01127   usleep(10000);                // Carlo says wait 10ms after this opcode.
01128 
01129 }
01141 void
01142 CCAENV1x90::SetWindowWidth(unsigned int nWidth)
01143 {
01144   REQUIRE(nWidth >= MINMATCHWIDTH, 
01145           FormatValue("Window width must be > %x",
01146                                     MINMATCHWIDTH).c_str());
01147   REQUIRE(nWidth <= MAXMATCHWIDTH, 
01148           FormatValue(" Window width must be <= 0x%x",
01149                                     MAXMATCHWIDTH).c_str());
01150 
01151   WriteMicro(CCAENV1x90Opcodes::SET_WIN_WIDTH);
01152   WriteMicro(nWidth);
01153   WaitMicroWrite();
01154 
01155 }
01167 void
01168 CCAENV1x90::SetWindowOffset(int nOffset)
01169 {
01170   REQUIRE(nOffset >= MINWINDOWOFFSET, 
01171           FormatValue("Window offset must be at least %d",
01172                            MINWINDOWOFFSET).c_str());
01173   REQUIRE(nOffset <= MAXWINDOWOFFSET,    
01174           FormatValue("Window offset must be no greater than %d",
01175                            MAXWINDOWOFFSET).c_str());
01176   WriteMicro(CCAENV1x90Opcodes::SET_WIN_OFFS);
01177   WriteMicro(nOffset);
01178   WaitMicroWrite();
01179 
01180 }
01181 
01198 void
01199 CCAENV1x90::SetExtraSearchMargin(unsigned int nMargin)
01200 {
01201   REQUIRE(nMargin >= 0, 
01202           FormatValue(" nMargin must be >=%d",
01203                                      MINEXTRAMARGIN).c_str());
01204   REQUIRE(nMargin <= 2047, 
01205           FormatValue("nMargin must be <= %d",
01206                                      MAXEXTRAMARGIN).c_str());
01207 
01208   WriteMicro(CCAENV1x90Opcodes::SET_SW_MARGIN);
01209   WriteMicro(nMargin);
01210   WaitMicroWrite();
01211 
01212 
01213 }
01228 void
01229 CCAENV1x90::SetRejectMargin(unsigned int nMargin)
01230 {
01231   REQUIRE(nMargin >= 0, 
01232           FormatValue("nMargin must be >= %d",
01233                                     MINREJECTMARGIN).c_str());
01234   REQUIRE(nMargin <= 2047, 
01235           FormatValue("nMargin must be <= %d",
01236                                     MAXREJECTMARGIN).c_str());
01237 
01238   WriteMicro(CCAENV1x90Opcodes::SET_REJ_MARGIN);
01239   WriteMicro(nMargin);
01240   WaitMicroWrite();
01241 }
01249 void
01250 CCAENV1x90::EnableTriggerTimeSubtraction()
01251 {
01252   WriteMicro(CCAENV1x90Opcodes::EN_SUB_TRG);
01253   WaitMicroWrite();
01254 }
01260 void 
01261 CCAENV1x90::DisableTriggerTimeSubtraction()
01262 {
01263   WriteMicro(CCAENV1x90Opcodes::DIS_SUB_TRG);
01264   WaitMicroWrite();
01265 
01266 }
01267 
01291 CCAENV1x90::TriggerConfiguration
01292 CCAENV1x90::GetTriggerConfiguration()
01293 {
01294   
01295   TriggerConfiguration config;
01296   MicroTransaction(CCAENV1x90Opcodes::READ_TRG_CONF,
01297                    &config, sizeof(config)/sizeof(short));
01298   return config;
01299 }
01313 unsigned int
01314 CCAENV1x90::GetMatchWindow(TriggerConfiguration Config)
01315 {
01316   return (Config.s_MatchWidth & MATCHMASK);
01317 }
01330 int 
01331 CCAENV1x90::GetWindowOffset(TriggerConfiguration Config)
01332 {
01333   int nOffset = (Config.s_MatchOffset & WINDOWOFFSETMASK);
01334 
01335   // nOffset is a signed 12 bit number... if necessary extend the  
01336   // sign; a & ~(a >> 1) is the highest set bit in a, if a is a mask
01337   // of contiguous 1's.
01338 
01339 
01340   if(nOffset & (WINDOWOFFSETMASK & ~(WINDOWOFFSETMASK >> 1))) {
01341     nOffset |= ~(WINDOWOFFSETMASK);
01342   }
01343   return nOffset;
01344 }
01358 unsigned int
01359 CCAENV1x90::GetExtraSearchMargin(TriggerConfiguration Config)
01360 {
01361   return Config.s_MatchExtra & EXTRAMARGINMASK;
01362 }
01363 
01375 unsigned int
01376 CCAENV1x90::GetRejectMargin(TriggerConfiguration Config)
01377 {
01378   return Config.s_RejectMargin & REJECTMARGINMASK;
01379 }
01395 bool
01396 CCAENV1x90::isTriggerTimeSubtracted(TriggerConfiguration Config)
01397 {
01398   return ((Config.s_Subtracting & TRUEBIT) != 0);
01399 }
01419 void
01420 CCAENV1x90::SetIndividualLSB(Resolution nResolution)
01421 {
01422 
01423   // Check the preconditions:
01424 
01425   REQUIRE(((nResolution == Res_25ps)     ||
01426            (nResolution == Res_100ps)    ||
01427            (nResolution == Res_200ps)    ||
01428            (nResolution == Res_800ps)), 
01429           "Resolution is not a legal value");
01430   if(nResolution == Res_25ps) {
01431     REQUIRE(m_fCanHiRes, "Only 1290 can be put in 25ps resolution");
01432   }
01433 
01434   WriteMicro(CCAENV1x90Opcodes::SET_TR_LEAD_LSB);
01435   WriteMicro(nResolution);
01436   WaitMicroWrite();
01437 
01438   // Only the 1290 can have 25ps resolution.. the flag variable
01439   // m_fIsHiResMode is used to keep track of this as there are things
01440   // you give up to get that resolution (most notably pair mode).
01441 
01442   if(nResolution == Res_25ps) {
01443     m_fIsHiResMode = true;
01444   } else {
01445     m_fIsHiResMode = false;
01446   }
01447 
01448 }
01449 
01450 
01473 void
01474 CCAENV1x90::SetEdgeDetectMode(EdgeMode nEdgeMode)
01475 {
01476   // Check preconditions.
01477 
01478   REQUIRE( ((nEdgeMode == EdgeMode_Pair)           ||
01479           (nEdgeMode == EdgeMode_Trailing)         ||
01480           (nEdgeMode == EdgeMode_Leading)          ||
01481           (nEdgeMode == EdgeMode_Both)),
01482          "Invalid edge mode");
01483   if(m_fCanHiRes & m_fIsHiResMode) {
01484     REQUIRE(nEdgeMode != EdgeMode_Pair,
01485           "Pair mode is not available in High resolution mode");
01486   }
01487 
01488   // Set the mode.
01489 
01490   WriteMicro(CCAENV1x90Opcodes::SET_DETECTION);
01491   WriteMicro(nEdgeMode);
01492   WaitMicroWrite();
01493 }
01494 
01506 CCAENV1x90::EdgeMode
01507 CCAENV1x90::GetEdgeDetectMode()
01508 {
01509   WriteMicro(CCAENV1x90Opcodes::READ_DETECTION);
01510   unsigned short n = ReadMicro();
01511   n   &= EDGEDETECTIONMASK;                     //  Only the bottom two bits have meaning
01512   return static_cast<EdgeMode>(n);
01513 
01514 }
01557 void
01558 CCAENV1x90::SetPairResolutions(LEResolution nLEResolution,
01559                                PWResolution nPWResolution)
01560 {
01561   // Check preconditions.
01562 
01563   REQUIRE((GetEdgeDetectMode() == EdgeMode_Pair),
01564         "Edge detection mode is not pair");
01565   REQUIRE( ((nLEResolution   == LE_100ps)     ||
01566           (nLEResolution   == LE_200ps)     ||
01567           (nLEResolution   == LE_400ps)     ||
01568           (nLEResolution   == LE_800ps)     ||
01569           (nLEResolution   == LE_1600ps)    ||
01570           (nLEResolution   == LE_3120ps)    ||
01571           (nLEResolution   == LE_6250ps)    ||
01572           (nLEResolution   == LE_12500ps)),
01573          "Leading edge resolution invalid");
01574 
01575   REQUIRE( ((nPWResolution  == PW_100ps)      ||
01576           (nPWResolution  == PW_200ps)      ||
01577           (nPWResolution  == PW_400ps)      ||
01578           (nPWResolution  == PW_800ps)      ||
01579           (nPWResolution  == PW_1600ps)     ||
01580           (nPWResolution  == PW_3200ps)     ||
01581           (nPWResolution  == PW_6250ps)     ||
01582           (nPWResolution  == PW_12500ps)    ||
01583           (nPWResolution  == PW_25ns)       ||
01584           (nPWResolution  == PW_50ns)       ||
01585           (nPWResolution  == PW_100ns)      ||
01586           (nPWResolution  == PW_200ns)      ||
01587           (nPWResolution  == PW_400ns)      ||
01588           (nPWResolution  == PW_800ns)),
01589          "Pair width resolution is invalid.");
01590 
01591   // Construct the settings word.
01592 
01593   unsigned short settings = nLEResolution | 
01594                             (nPWResolution << PWRESOLUTIONRSHIFT);
01595 
01596 
01597   // set the pair resolutions.
01598   WriteMicro(CCAENV1x90Opcodes::SET_PAIR_RES);
01599   WriteMicro(settings);
01600   WaitMicroWrite();
01601 
01602 }
01620 unsigned short
01621 CCAENV1x90::GetResolution()
01622 {
01623   WriteMicro(CCAENV1x90Opcodes::READ_RES);
01624   return ReadMicro();
01625 
01626 }
01644 CCAENV1x90::Resolution
01645 CCAENV1x90::InterpretEdgeResolution(unsigned short nResolution)
01646 {
01647   // Check preconditions:
01648 
01649   REQUIRE(GetEdgeDetectMode() != EdgeMode_Pair,
01650         "Edge resolution asked for when module in pair mode");
01651 
01652   //
01653   
01654   unsigned short nMask = nResolution & 
01655                          EDGERESOLUTIONMASK; // Mask off resolution and
01656   return static_cast<Resolution>(nMask); // Return as resolution 
01657 }
01679 CCAENV1x90::LEResolution
01680 CCAENV1x90::InterpretLEResolution(unsigned short nResolution)
01681 {
01682   // Check preconditions:
01683 
01684   REQUIRE(GetEdgeDetectMode() == EdgeMode_Pair,
01685         "LE resolution requested with module not in pair mode"); 
01686 
01687   // 
01688 
01689   unsigned short nMask = nResolution & LERESOLUTIONMASK;
01690   return static_cast<LEResolution>(nMask);
01691     
01692 }
01721 CCAENV1x90::PWResolution
01722 CCAENV1x90::InterpretWidthResolution(unsigned short nResolution)
01723 {
01724   // Check the precondition:
01725 
01726   REQUIRE(GetEdgeDetectMode() == EdgeMode_Pair,
01727         "PW resolution requested when not in pair mode");
01728 
01729   //
01730   unsigned short nMask = (nResolution & PWRESOLUTIONMASK) >> 
01731                           PWRESOLUTIONRSHIFT;
01732   return static_cast<PWResolution>(nMask);
01733 }
01749 void
01750 CCAENV1x90::SetDoubleHitResolution(DeadTime nDeadTime) 
01751 { 
01752   // Check the preconditions
01753 
01754   REQUIRE((nDeadTime == DT_5ns)         ||
01755         (nDeadTime == DT_10ns)        ||
01756         (nDeadTime == DT_30ns)        ||
01757         (nDeadTime == DT_100ns),
01758         "Invalid dead time value");
01759   //
01760   WriteMicro(CCAENV1x90Opcodes::SET_DEAD_TIME);
01761   WriteMicro(nDeadTime);
01762   WaitMicroWrite();
01763 
01764 }
01776 CCAENV1x90::DeadTime
01777 CCAENV1x90::GetDoubleHitResolution()
01778 {
01779   WriteMicro(CCAENV1x90Opcodes::READ_DEAD_TIME);
01780   unsigned short nMask = ReadMicro();
01781   nMask &= 3;
01782   return static_cast<DeadTime>(nMask);
01783 
01784 }
01789 void
01790 CCAENV1x90::EnableTDCEncapsulation()
01791 {
01792   WriteMicro(CCAENV1x90Opcodes::EN_HEADER_TRAILER);
01793   WaitMicroWrite();
01794 }
01795 
01800 void
01801 CCAENV1x90::DisableTDCEncapsulation()
01802 {
01803   WriteMicro(CCAENV1x90Opcodes::DIS_HEADER_TRAILER);
01804   WaitMicroWrite();
01805 }
01814 bool
01815 CCAENV1x90::isTDCEncapsulationOn()
01816 {
01817   WriteMicro(CCAENV1x90Opcodes::READ_HEADER_TRAILER);
01818   return (ReadMicro() & TRUEBIT) != 0;
01819 
01820 }
01843 void
01844 CCAENV1x90::SetMaxHitsPerEvent(HitMax nHits)
01845 {
01846   // Check validity of nHits parameter (precondition)
01847 
01848   REQUIRE((nHits == HITS_0)              ||
01849         (nHits == HITS_1)              ||
01850         (nHits == HITS_2)              ||
01851         (nHits == HITS_4)              ||
01852         (nHits == HITS_8)              ||
01853         (nHits == HITS_16)             ||
01854         (nHits == HITS_32)             ||
01855         (nHits == HITS_64)             ||
01856         (nHits == HITS_128)            ||
01857         (nHits == HITS_UNLIMITED),
01858         "Invalid nHits parameter value");
01859 
01860   //  Set the device:
01861 
01862   WriteMicro(CCAENV1x90Opcodes::SET_EVENT_SIZE);
01863   WriteMicro(static_cast<unsigned short>(nHits));
01864   WaitMicroWrite();
01865 }
01882 CCAENV1x90::HitMax
01883 CCAENV1x90::GetMaxHitsPerEvent()
01884 {
01885   WriteMicro(CCAENV1x90Opcodes::READ_EVENT_SIZE);
01886   unsigned short nMask = ReadMicro();
01887   return static_cast<HitMax>(nMask);
01888 }
01889 
01895 void
01896 CCAENV1x90::EnableErrorMark()
01897 {
01898   WriteMicro(CCAENV1x90Opcodes::EN_ERROR_MARK);
01899   WaitMicroWrite();
01900 }
01905 void
01906 CCAENV1x90::DisableErrorMark()
01907 {
01908   WriteMicro(CCAENV1x90Opcodes::DIS_ERROR_MARK);
01909   WaitMicroWrite();
01910 }
01915 void
01916 CCAENV1x90::EnableBypassOnError()
01917 {
01918   WriteMicro(CCAENV1x90Opcodes::EN_ERROR_BYPASS);
01919   WaitMicroWrite();
01920 }
01925 void
01926 CCAENV1x90::DisableBypassOnError()
01927 {
01928   WriteMicro(CCAENV1x90Opcodes::DIS_ERROR_BYPASS);
01929   WaitMicroWrite();
01930 }
01957 void
01958 CCAENV1x90::SetErrorEnables(unsigned short nErrors)
01959 {
01960   // Check the preconditions..
01961 
01962   REQUIRE((nErrors & ~( ERR_VERNIER         &
01963                       ERR_SELECT          &
01964                       ERR_L1PARITY        &
01965                       ERR_TFIFOPARITY     &
01966                       ERR_MATCHERROR      &
01967                       ERR_RFIFOPARITY     &
01968                       ERR_RDOSTATE        &
01969                       ERR_SUPPARITY       &
01970                       ERR_CTLPARITY       &
01971                       ERR_JTAGPARITY)),
01972         "Error mask contains extra set bits.");
01973 
01974   // Set the device.
01975 
01976   WriteMicro(CCAENV1x90Opcodes::SET_ERROR_TYPES);
01977   WriteMicro(nErrors);
01978   WaitMicroWrite();
01979 }
01980 
01987 unsigned short
01988 CCAENV1x90::GetErrorEnables()
01989 {
01990   WriteMicro(CCAENV1x90Opcodes::READ_ERROR_TYPES);
01991   return ReadMicro();
01992 }
01993 
01994 
02013 void
02014 CCAENV1x90::SetL1Size(L1Size nL1Size)
02015 {
02016   // Check precondition:
02017 
02018   REQUIRE((nL1Size   == L1_2wds)       ||
02019         (nL1Size   == L1_4wds)       ||
02020         (nL1Size   == L1_8wds)       ||
02021         (nL1Size   == L1_16wds)      ||
02022         (nL1Size   == L1_32wds)      ||
02023         (nL1Size   == L1_64wds)      ||
02024         (nL1Size   == L1_128wds)     ||
02025         (nL1Size   == L1_256wds),
02026         "L1 size selector is invalid");
02027 
02028   //
02029   
02030   WriteMicro(CCAENV1x90Opcodes::SET_FIFO_SIZE);
02031   WriteMicro(nL1Size);
02032   WaitMicroWrite();
02033   
02034 
02035 }
02041 CCAENV1x90::L1Size
02042 CCAENV1x90::GetL1Size()
02043 {
02044   WriteMicro(CCAENV1x90Opcodes::READ_FIFO_SIZE);
02045   return static_cast<L1Size>(ReadMicro());
02046 }
02047 
02064 void
02065 CCAENV1x90::EnableChannel(unsigned short nChannel)
02066 {
02067   REQUIRE(nChannel < m_nChannels, "Channel number out of range");
02068 
02069   //
02070   WriteMicro(CCAENV1x90Opcodes::EN_CHANNEL | nChannel);
02071   WaitMicroWrite();
02072 }
02086 void
02087 CCAENV1x90::DisableChannel(unsigned short nChannel)
02088 {
02089   REQUIRE(nChannel < m_nChannels, "Channel Number out of range");
02090 
02091   //
02092 
02093   WriteMicro(CCAENV1x90Opcodes::DIS_CHANNEL | nChannel);
02094   WaitMicroWrite();
02095 
02096 }
02097 
02101 void
02102 CCAENV1x90::EnableAllChannels()
02103 {
02104   WriteMicro(CCAENV1x90Opcodes::EN_ALL_CH);
02105   WaitMicroWrite();
02106 }
02110 void
02111 CCAENV1x90::DisableAllChannels()
02112 {
02113   WriteMicro(CCAENV1x90Opcodes::DIS_ALL_CH);
02114   WaitMicroWrite();
02115 }
02128 void
02129 CCAENV1x90::SetChannelEnables(vector<unsigned short> nMask)
02130 {
02131   // Check the mask is the proper size:
02132 
02133   REQUIRE(nMask.size() == m_nChannels/(sizeof(short)*8),
02134         "Enables mask is not the right size.");
02135 
02136   // Marshall the vector into an array so we can call WriteMicroBlock
02137 
02138   unsigned short* pWords = new unsigned short[nMask.size() + 1];
02139 
02140   pWords[0] = CCAENV1x90Opcodes::WRITE_EN_PATTERN;
02141   for(int i =0; i < nMask.size(); i++) {
02142     pWords[i+1] = nMask[i];
02143   }
02144 
02145   WriteMicroBlock(pWords, nMask.size()+1);
02146   WaitMicroWrite();
02147 
02148   delete []pWords;
02149 
02150 }
02166 void
02167 CCAENV1x90::GetChannelEnables(vector<unsigned short>& masks)
02168 {
02169   unsigned int nMasks = m_nChannels/(sizeof(short)*8);
02170 
02171   unsigned short* localMasks = new unsigned short[nMasks];
02172 
02173   MicroTransaction(CCAENV1x90Opcodes::READ_EN_PATTERN,
02174                    localMasks, nMasks);
02175 
02176   for(int i =0; i < nMasks; i++) {
02177     masks.push_back(localMasks[i]);
02178   }
02179   delete []localMasks;
02180 
02181 }
02182 
02198 void
02199 CCAENV1x90::SetChipEnables(unsigned short nChip,
02200                            unsigned int nMask)
02201 {
02202   // Check the preconditions:
02203 
02204   REQUIRE(nChip < m_nChipCount,
02205         "Chip number is not valid for this model");
02206   
02207   //  Issue the opcode.  Note that nMask must be busted
02208   //  apart into a low and high word that get written to the
02209   //  micro.
02210   
02211   unsigned short wordMask;
02212 
02213   WriteMicro(CCAENV1x90Opcodes::WRITE_EN_PATTERN32 | nChip);
02214 
02215   wordMask = LO(nMask);
02216   WriteMicro(wordMask);
02217 
02218   wordMask = HI(nMask);
02219   WriteMicro(wordMask);
02220   WaitMicroWrite();
02221 
02222 }
02223 
02239 unsigned int
02240 CCAENV1x90::GetChipEnables(unsigned short nChip)
02241 {
02242   // Check preconditions:
02243 
02244   REQUIRE(nChip < m_nChipCount,
02245           FormatValue("Invalid chip number %d",
02246                                     nChip).c_str());
02247 
02248   // Fetch the mask out in two chunks.  The first
02249   // word has the low order channels, the second, the high:
02250 
02251   unsigned int mask;
02252 
02253   WriteMicro(CCAENV1x90Opcodes::READ_EN_PATTERN32 | nChip);
02254 
02255   mask = (static_cast<unsigned int>(ReadMicro())) & 0xffff;
02256   unsigned int top = ReadMicro();
02257   mask |= (top << 16);
02258 
02259 
02260   return mask;
02261 
02262 }
02279 void
02280 CCAENV1x90::SetGlobalOffset(unsigned short nCoarse,
02281                             unsigned short nVernier)
02282 {
02283   // Check the preconditions:
02284 
02285   REQUIRE(nCoarse <= COARSEMAX, 
02286           FormatValue("Global offset coarse value %d",
02287                                     nCoarse).c_str());
02288   REQUIRE(nVernier <= VERNIERMAX,
02289           FormatValue("Vernier offset is invalid: %d",
02290                                     nVernier).c_str());
02291 
02292   // Set the values:
02293 
02294   WriteMicro(CCAENV1x90Opcodes::SET_GLOB_OFFS);
02295   WriteMicro(nCoarse);
02296   WriteMicro(nVernier);
02297   WaitMicroWrite();
02298 
02299 }
02300 
02313 void
02314 CCAENV1x90::ReadGlobalOffset(unsigned short& nCoarse,
02315                              unsigned short& nVernier)
02316 {
02317   WriteMicro(CCAENV1x90Opcodes::READ_GLOB_OFFS);
02318   nCoarse = (ReadMicro()  & COARSEMASK);
02319   nVernier= (ReadMicro()  & VERNIERMASK);
02320 
02321 }
02322 
02338 void 
02339 CCAENV1x90::SetChannelOffset(unsigned short nChannel,
02340                              unsigned short nOffset)
02341 {
02342   // Check the preconditions:
02343 
02344   REQUIRE(nChannel < m_nChannels,
02345         " Channel number out of range");
02346   REQUIRE(nOffset  <= CHANOFFSETMAX,
02347           FormatValue("Offset value out of range: %d",
02348                                     nOffset).c_str());
02349 
02350   // Set the micro:
02351 
02352   WriteMicro(CCAENV1x90Opcodes::SET_ADJUST_CH | nChannel);
02353   WriteMicro(nOffset);
02354   WaitMicroWrite();
02355 }
02370 unsigned short
02371 CCAENV1x90::GetChannelOffset(unsigned int nChannel)
02372 {
02373   // check the preconditions:
02374 
02375   REQUIRE(nChannel < m_nChannels,
02376         "Channel number out of range");
02377 
02378   // Get and return the value:
02379 
02380   WriteMicro(CCAENV1x90Opcodes::READ_ADJUST_CH | nChannel);
02381   return (ReadMicro() & CHANOFFSETMASK);
02382 }
02415 void
02416 CCAENV1x90::CalibrateDelayLine(unsigned short nChip,
02417                                unsigned short Tap1Contact,
02418                                unsigned short Tap2Contact,
02419                                unsigned short Tap3Contact,
02420                                unsigned short Tap4Contact)
02421 {
02422   // check the preconditions:
02423 
02424   REQUIRE(nChip < m_nChipCount,
02425         "Chip number is not in range");
02426 
02427   REQUIRE((Tap1Contact & ~(TAP_CONTACT1 | TAP_CONTACT2 | TAP_CONTACT3)) == 0,
02428         " Tap 1 contact has extra bits"); 
02429   REQUIRE((Tap2Contact & ~(TAP_CONTACT1 | TAP_CONTACT2 | TAP_CONTACT3)) == 0,
02430         " Tap 1 contact has extra bits");
02431   REQUIRE((Tap3Contact & ~(TAP_CONTACT1 | TAP_CONTACT2 | TAP_CONTACT3)) == 0,
02432         " Tap 1 contact has extra bits");
02433   REQUIRE((Tap4Contact & ~(TAP_CONTACT1 | TAP_CONTACT2 | TAP_CONTACT3)) == 0,
02434         " Tap 1 contact has extra bits");
02435 
02436   // Set the delay line calibration.
02437   
02438   unsigned short TapMask = (Tap1Contact) |
02439                            (Tap2Contact << 3) |
02440                            (Tap3Contact << 6) |
02441                            (Tap4Contact << 9);
02442 
02443 
02444   WriteMicro(CCAENV1x90Opcodes::SET_RC_ADJ | nChip);
02445   WriteMicro(TapMask);
02446   WaitMicroWrite();
02447 }
02468 void
02469 CCAENV1x90::GetDelayLineCalibration(unsigned short  nChip,
02470                                     unsigned short& Tap1Contact,
02471                                     unsigned short& Tap2Contact,
02472                                     unsigned short& Tap3Contact,
02473                                     unsigned short& Tap4Contact)
02474 {
02475   WriteMicro(CCAENV1x90Opcodes::READ_RC_ADJ | nChip);
02476   unsigned short TapMask = ReadMicro();
02477 
02478   Tap1Contact = (TapMask & TAPCONTACTMASK);
02479   Tap2Contact = (TapMask >> TAPCONTACTRSHIFT) & TAPCONTACTMASK;
02480   Tap3Contact = (TapMask >> (2*TAPCONTACTRSHIFT)) & TAPCONTACTMASK;
02481   Tap4Contact = (TapMask >> (3*TAPCONTACTRSHIFT)) & TAPCONTACTMASK;
02482 
02483 }
02490 void
02491 CCAENV1x90::SaveDelayLineCalibrations()
02492 {
02493   WriteMicro(CCAENV1x90Opcodes::SAVE_RC_ADJ);
02494   WaitMicroWrite();
02495 
02496 }
02514 unsigned int
02515 CCAENV1x90::GetChipId(unsigned short nChip)
02516 {
02517   REQUIRE(nChip < m_nChipCount,
02518         "Chip number invalid for this board");
02519 
02520 
02521   WriteMicro(CCAENV1x90Opcodes::READ_TDC_ID | nChip);
02522 
02523   // 16 Is not a magic number.. It's the number of bits in a word.
02524   
02525   unsigned int nId = ReadMicro();
02526   nId             |= (static_cast<unsigned int>(ReadMicro())) << 16;
02527   return nId;
02528 }
02529 
02530 
02545 void
02546 CCAENV1x90::GetuCFirmwareInfo(unsigned short& nRevision,
02547                               unsigned short& nDay,
02548                               unsigned short& nMonth,
02549                               unsigned short& nYear)
02550 {
02551   WriteMicro(CCAENV1x90Opcodes::REV_DATE_MICRO_FW);
02552   nRevision = ReadMicro();
02553   nDay      = ReadMicro();
02554   nMonth    = ReadMicro();
02555   nYear     = ReadMicro();
02556 }
02557 
02570 unsigned short
02571 CCAENV1x90::GetChipErrors(unsigned short nChip)
02572 {
02573   REQUIRE(nChip < m_nChipCount,
02574         "Chip number is out of range for this module");
02575 
02576   WriteMicro(CCAENV1x90Opcodes::READ_ERROR_STATUS | nChip);
02577 
02578   unsigned short nErrors = ReadMicro();
02579 
02580   nErrors &= ~(ERR_VERNIER     |
02581                ERR_COARSE      |
02582                ERR_SELECT      |
02583                ERR_L1PARITY    |
02584                ERR_TFIFOPARITY |
02585                ERR_MATCHERROR  |
02586                ERR_RFIFOPARITY |
02587                ERR_RDOSTATE    |
02588                ERR_SUPPARITY   |
02589                ERR_CTLPARITY   |
02590                ERR_JTAGPARITY);
02591   return nErrors;
02592 }
02608 void
02609 CCAENV1x90::EnableTestMode(unsigned int  nValue)
02610 {
02611   // Validate preconditions:
02612 
02613   REQUIRE((nValue & ~(MAXTESTVALUE)) == 0,
02614         "The data value has extraneous bits");
02615 
02616   // Break up thed data longword into hi lo words:
02617   //  0xffff is just a word with all bits set., 16 the # bits in a word
02618 
02619   unsigned short nLow   = LO(nValue);
02620   unsigned short nHigh  = HI(nValue);
02621 
02622   WriteMicro(CCAENV1x90Opcodes::ENABLE_TEST_MODE);
02623   WriteMicro(nLow);
02624   WriteMicro(nHigh);
02625   WaitMicroWrite();
02626 
02627 }
02628 
02633 void
02634 CCAENV1x90::DisableTestMode()
02635 {
02636   WriteMicro(CCAENV1x90Opcodes::DISABLE_TEST_MODE);
02637   WaitMicroWrite();
02638 }
02639 
02641 
02661 unsigned int
02662 CCAENV1x90::ReadData(void* pBuffer,
02663                      unsigned int nMaxLongs)
02664 {
02665   if(m_fTriggerMatching) {
02666     return ReadPacket(pBuffer, nMaxLongs);
02667   } else {
02668     return ReadValid(pBuffer, nMaxLongs);
02669   }
02670 }
02697 unsigned int
02698 CCAENV1x90::ReadPacket(void* pBuffer,
02699                        unsigned int nMaxLongs)
02700 {
02701   unsigned long* pPacket = (unsigned long*)pBuffer;
02702   unsigned int   nRead   = 0;
02703 
02704   // Loop over the read until we get a data word that has
02705   // either the TDC_TRAILER or FILLER_LONG type  mask value.
02706   // Note that if we run out of user buffer we just stop incrementing
02707   // the counter/pointer.
02708 
02709   bool done(false);
02710   while(!done) {
02711     unsigned long datum = m_pRegisters.peekl(OffsetL(OutputBuffer));
02712     *pPacket            = datum;
02713     if(isGlobalTrailer(datum) || isFiller(datum)) {
02714       done = true;              // Last read.
02715     }
02716     if(nRead < nMaxLongs) {     // overwrite last word if output full.
02717       pPacket++;
02718       nRead++;
02719     }
02720   }
02721   
02722   return nRead;
02723 }
02738 unsigned int 
02739 CCAENV1x90::ReadValid(void* pBuffer, unsigned int nMaxLongs)
02740 {
02741   unsigned long* pLongs = (unsigned long*)pBuffer;
02742   unsigned int   nRead  = 0;
02743   bool           done   = false;
02744 
02745   while(!done) {
02746     unsigned long datum = m_pRegisters.peekl(OffsetL(OutputBuffer));
02747     *pLongs++          = datum;
02748     nRead++;
02749 
02750     if(isGlobalTrailer(datum) ||
02751        isFiller(datum)    ||
02752        (nRead == nMaxLongs)) {
02753       done = true;
02754     }
02755   }
02756 
02757   return nRead;
02758 }
02759 
02761 
02779 bool
02780 CCAENV1x90::ValidBoard(CVmeModule& pRom)
02781 {
02782   // Check the manufacturer's code (OUI):
02783   
02784   unsigned long oui = ReadPromLong(pRom, WOUI2); // Read oui from prom.
02785   if(oui != 0x0040e6) {
02786     return false;
02787   }
02788 
02789   // Check the board version:
02790 
02791   unsigned long nModel = ReadPromLong(pRom, WModelNumber2);
02792   if((nModel != 1190) && (nModel != 1290)) {
02793     return false;
02794   }
02795 
02796   // 1190's can be either type a or b, 1290's must be a or n
02797 
02798   unsigned char nType = 
02799     pRom.peekw(OffsetW(WBoardVersion)) & 0xff;
02800 
02801   if(nModel == 1190) {
02802     if((nType != ModuleVersion::A) && 
02803        (nType != ModuleVersion::B)) {
02804       return false;
02805     }
02806   }
02807   else {                        // Already know from above it's a 1290
02808     if((nType != ModuleVersion::A) && 
02809        (nType != ModuleVersion::N)) {
02810       return false;
02811     }
02812   }
02813   // Ok board.
02814 
02815   return true;
02816 }
02817 
02842 void
02843 CCAENV1x90::BoardProperties(CVmeModule& pROM)
02844 {
02845   m_nModel = ReadPromLong(pROM,WModelNumber2);
02846 
02847   // Sub module gets encoded as a letter:
02848 
02849   unsigned short ntype= 
02850     pROM.peekw(OffsetW(WBoardVersion)) & 0xff;
02851   if(ntype == ModuleVersion::A) {
02852     m_cVersion = 'A';
02853    }
02854   else if (ntype == ModuleVersion::B) {
02855     m_cVersion = 'B';
02856   }
02857   else if (ntype ==  ModuleVersion::N) {
02858     m_cVersion = 'N';
02859   }
02860   else {                        // Not allowed.
02861     throw string("Unrecognized module subtype, not A,B, nor N");
02862   }
02863 
02864   // Serial number is a prom word:
02865 
02866   m_nSerialNumber = 
02867     (pROM.peekw(OffsetW(WSerialNumber1)) & 0xff) << 8;
02868   m_nSerialNumber |=
02869     (pROM.peekw(OffsetW(WSerialNumber0)) & 0xff);
02870 
02871   // Board revision is 4 bytes (a true long word).
02872   // this will be built up by trickery from a 3 byte long:
02873 
02874   m_nBoardRevision = ReadPromLong(pROM, WRevision3); // top 24 bits
02875   m_nBoardRevision = (m_nBoardRevision << 8) |
02876     (pROM.peekw(OffsetW(WRevision0)) & 0xff); // bottom 8.
02877 
02878   // Module specific info is as follows:
02879   //           chans   chips  CanHires
02880   //   1190 A:  128      4     no
02881   //   1190 B:   64      2     no
02882   //   1290 A:   32      4     yes
02883   //   1290 N:   16      2     yes
02884 
02885   if(m_nModel == 1190) {
02886     m_fCanHiRes  = false;
02887     if(m_cVersion == 'A') {
02888       m_nChannels = 128;
02889       m_nChipCount=   4;
02890     } 
02891     else {
02892       m_nChannels =  64;
02893       m_nChipCount=   2;
02894     }
02895   } 
02896   else {                        // 1290
02897     m_fCanHiRes = true;
02898     if(m_cVersion == 'A') {
02899       m_nChannels  = 32;
02900       m_nChipCount =  4;
02901     } 
02902     else {
02903       m_nChannels  = 16;
02904       m_nChipCount =  2;
02905     }
02906   }
02907 
02908   // Now use the SR to figure out if the module is in trigger
02909   // match mode.  We don't need to conditionalize the
02910   // resolution check for hires as the hi-res mode is not
02911   // an allowed resolution combination for the 1190:
02912   
02913   unsigned short sr = SR();
02914   m_fTriggerMatching = (sr & StatusRegister::TRG_MATCH) == 
02915                                         StatusRegister::TRG_MATCH;
02916   m_fIsHiResMode      = (sr & StatusRegister::RESOLUTIONMASK) ==
02917                                         StatusRegister::RES_25ps;
02918 
02919 }
02920 
02930 unsigned short
02931 CCAENV1x90::SR()
02932 {
02933   return m_pRegisters.peekw(OffsetW(WStatusRegister));
02934 }
02935 
02954 bool
02955 CCAENV1x90::isSetSR(unsigned short bitnum)
02956 {
02957   return (SR() & (1 << bitnum)) != 0;
02958 }
02959 
02970 void
02971 CCAENV1x90::WriteCR(unsigned short mask)
02972 {
02973   m_pRegisters.pokew(mask, OffsetW(WControlRegister));
02974 }
02975 
02984 unsigned short
02985 CCAENV1x90::ReadCR()
02986 {
02987   return m_pRegisters.peekw(OffsetW(WControlRegister));
02988 }
02998 void 
02999 CCAENV1x90::BitSetCR(unsigned short bit)
03000 {
03001   unsigned short cr = ReadCR();
03002   cr |= (1 << bit);
03003   WriteCR(cr);
03004 }
03005 
03014 void
03015 CCAENV1x90::BitClearCR(unsigned short bit)
03016 {
03017   unsigned short cr = ReadCR();
03018   cr &= ~(1 << bit);
03019   WriteCR(cr);
03020 }
03021 
03022 
03038 unsigned long
03039 CCAENV1x90::ReadPromLong(CVmeModule& prombase,
03040                          unsigned long ByteOffset)
03041 {
03042   unsigned long n;              // Result long.
03043   unsigned long WordOffset = OffsetW(ByteOffset);
03044 
03045   n  = (prombase.peekw(WordOffset)   & 0xff) << 16;
03046   n |= (prombase.peekw(WordOffset+2) & 0xff) <<  8;
03047   n |= (prombase.peekw(WordOffset+4) & 0xff);
03048 
03049   return n;
03050 
03051 }
03055 void
03056 CCAENV1x90::WaitMicroWrite()
03057 {
03058 
03059   while((m_pRegisters.peekw(OffsetW(WMicroHandshake)) & 
03060          MicroHandshake::WRITE_OK)  == 0) 
03061     ;                           // Spin on the register...
03062 
03063 }
03064   
03075 void 
03076 CCAENV1x90::WriteMicro(unsigned short nWord)
03077 {
03078   // Wait for the micro to be writable...
03079 
03080   WaitMicroWrite();
03081 
03082   // Write the word.
03083   
03084   m_pRegisters.pokew(nWord, OffsetW(WMicroData));
03085 
03086 }
03100 unsigned short
03101 CCAENV1x90::ReadMicro()
03102 {
03103   // Wait for data to be presented:
03104 
03105   while((m_pRegisters.peekw(OffsetW(WMicroHandshake)) & 
03106          MicroHandshake::READ_OK)  == 0)
03107     ;                           // Spin on the bit.
03108 
03109   // Return the data:
03110 
03111   return m_pRegisters.peekw(OffsetW(WMicroData));
03112 }
03126 void 
03127 CCAENV1x90::WriteMicroBlock(void* pWords,
03128                             unsigned int nWords)
03129 {
03130   unsigned short* pW = (unsigned short*) pWords;
03131 
03132   for(int i = 0; i < nWords; i++) {
03133     WriteMicro(*pW++);
03134   }
03135 }
03148 void
03149 CCAENV1x90::ReadMicroBlock(void* pWords, 
03150                            unsigned int nWords)
03151 {
03152   unsigned short* pW = (unsigned short*) pWords;
03153 
03154   for(int i =0; i < nWords; i++) {
03155     *pW++ = ReadMicro();
03156   }
03157 }
03173 void 
03174 CCAENV1x90::MicroTransaction(unsigned short opcode,
03175                              void*          pWords,
03176                              unsigned int   nWords)
03177 {
03178   WriteMicro(opcode);
03179   ReadMicroBlock(pWords, nWords);
03180 }

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