CAENcard.cpp

Go to the documentation of this file.
00001 /*
00002                     GNU GENERAL PUBLIC LICENSE
00003                        Version 2, June 1991
00004 
00005  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
00006                        59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00007  Everyone is permitted to copy and distribute verbatim copies
00008  of this license document, but changing it is not allowed.
00009 
00010                             Preamble
00011 
00012   The licenses for most software are designed to take away your
00013 freedom to share and change it.  By contrast, the GNU General Public
00014 License is intended to guarantee your freedom to share and change free
00015 software--to make sure the software is free for all its users.  This
00016 General Public License applies to most of the Free Software
00017 Foundation's software and to any other program whose authors commit to
00018 using it.  (Some other Free Software Foundation software is covered by
00019 the GNU Library General Public License instead.)  You can apply it to
00020 your programs, too.
00021 
00022   When we speak of free software, we are referring to freedom, not
00023 price.  Our General Public Licenses are designed to make sure that you
00024 have the freedom to distribute copies of free software (and charge for
00025 this service if you wish), that you receive source code or can get it
00026 if you want it, that you can change the software or use pieces of it
00027 in new free programs; and that you know you can do these things.
00028 
00029   To protect your rights, we need to make restrictions that forbid
00030 anyone to deny you these rights or to ask you to surrender the rights.
00031 These restrictions translate to certain responsibilities for you if you
00032 distribute copies of the software, or if you modify it.
00033 
00034   For example, if you distribute copies of such a program, whether
00035 gratis or for a fee, you must give the recipients all the rights that
00036 you have.  You must make sure that they, too, receive or can get the
00037 source code.  And you must show them these terms so they know their
00038 rights.
00039 
00040   We protect your rights with two steps: (1) copyright the software, and
00041 (2) offer you this license which gives you legal permission to copy,
00042 distribute and/or modify the software.
00043 
00044   Also, for each author's protection and ours, we want to make certain
00045 that everyone understands that there is no warranty for this free
00046 software.  If the software is modified by someone else and passed on, we
00047 want its recipients to know that what they have is not the original, so
00048 that any problems introduced by others will not reflect on the original
00049 authors' reputations.
00050 
00051   Finally, any free program is threatened constantly by software
00052 patents.  We wish to avoid the danger that redistributors of a free
00053 program will individually obtain patent licenses, in effect making the
00054 program proprietary.  To prevent this, we have made it clear that any
00055 patent must be licensed for everyone's free use or not licensed at all.
00056 
00057   The precise terms and conditions for copying, distribution and
00058 modification follow.
00059 
00060                     GNU GENERAL PUBLIC LICENSE
00061    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
00062 
00063   0. This License applies to any program or other work which contains
00064 a notice placed by the copyright holder saying it may be distributed
00065 under the terms of this General Public License.  The "Program", below,
00066 refers to any such program or work, and a "work based on the Program"
00067 means either the Program or any derivative work under copyright law:
00068 that is to say, a work containing the Program or a portion of it,
00069 either verbatim or with modifications and/or translated into another
00070 language.  (Hereinafter, translation is included without limitation in
00071 the term "modification".)  Each licensee is addressed as "you".
00072 
00073 Activities other than copying, distribution and modification are not
00074 covered by this License; they are outside its scope.  The act of
00075 running the Program is not restricted, and the output from the Program
00076 is covered only if its contents constitute a work based on the
00077 Program (independent of having been made by running the Program).
00078 Whether that is true depends on what the Program does.
00079 
00080   1. You may copy and distribute verbatim copies of the Program's
00081 source code as you receive it, in any medium, provided that you
00082 conspicuously and appropriately publish on each copy an appropriate
00083 copyright notice and disclaimer of warranty; keep intact all the
00084 notices that refer to this License and to the absence of any warranty;
00085 and give any other recipients of the Program a copy of this License
00086 along with the Program.
00087 
00088 You may charge a fee for the physical act of transferring a copy, and
00089 you may at your option offer warranty protection in exchange for a fee.
00090 
00091   2. You may modify your copy or copies of the Program or any portion
00092 of it, thus forming a work based on the Program, and copy and
00093 distribute such modifications or work under the terms of Section 1
00094 above, provided that you also meet all of these conditions:
00095 
00096     a) You must cause the modified files to carry prominent notices
00097     stating that you changed the files and the date of any change.
00098 
00099     b) You must cause any work that you distribute or publish, that in
00100     whole or in part contains or is derived from the Program or any
00101     part thereof, to be licensed as a whole at no charge to all third
00102     parties under the terms of this License.
00103 
00104     c) If the modified program normally reads commands interactively
00105     when run, you must cause it, when started running for such
00106     interactive use in the most ordinary way, to print or display an
00107     announcement including an appropriate copyright notice and a
00108     notice that there is no warranty (or else, saying that you provide
00109     a warranty) and that users may redistribute the program under
00110     these conditions, and telling the user how to view a copy of this
00111     License.  (Exception: if the Program itself is interactive but
00112     does not normally print such an announcement, your work based on
00113     the Program is not required to print an announcement.)
00114 
00115 These requirements apply to the modified work as a whole.  If
00116 identifiable sections of that work are not derived from the Program,
00117 and can be reasonably considered independent and separate works in
00118 themselves, then this License, and its terms, do not apply to those
00119 sections when you distribute them as separate works.  But when you
00120 distribute the same sections as part of a whole which is a work based
00121 on the Program, the distribution of the whole must be on the terms of
00122 this License, whose permissions for other licensees extend to the
00123 entire whole, and thus to each and every part regardless of who wrote it.
00124 
00125 Thus, it is not the intent of this section to claim rights or contest
00126 your rights to work written entirely by you; rather, the intent is to
00127 exercise the right to control the distribution of derivative or
00128 collective works based on the Program.
00129 
00130 In addition, mere aggregation of another work not based on the Program
00131 with the Program (or with a work based on the Program) on a volume of
00132 a storage or distribution medium does not bring the other work under
00133 the scope of this License.
00134 
00135   3. You may copy and distribute the Program (or a work based on it,
00136 under Section 2) in object code or executable form under the terms of
00137 Sections 1 and 2 above provided that you also do one of the following:
00138 
00139     a) Accompany it with the complete corresponding machine-readable
00140     source code, which must be distributed under the terms of Sections
00141     1 and 2 above on a medium customarily used for software interchange; or,
00142 
00143     b) Accompany it with a written offer, valid for at least three
00144     years, to give any third party, for a charge no more than your
00145     cost of physically performing source distribution, a complete
00146     machine-readable copy of the corresponding source code, to be
00147     distributed under the terms of Sections 1 and 2 above on a medium
00148     customarily used for software interchange; or,
00149 
00150     c) Accompany it with the information you received as to the offer
00151     to distribute corresponding source code.  (This alternative is
00152     allowed only for noncommercial distribution and only if you
00153     received the program in object code or executable form with such
00154     an offer, in accord with Subsection b above.)
00155 
00156 The source code for a work means the preferred form of the work for
00157 making modifications to it.  For an executable work, complete source
00158 code means all the source code for all modules it contains, plus any
00159 associated interface definition files, plus the scripts used to
00160 control compilation and installation of the executable.  However, as a
00161 special exception, the source code distributed need not include
00162 anything that is normally distributed (in either source or binary
00163 form) with the major components (compiler, kernel, and so on) of the
00164 operating system on which the executable runs, unless that component
00165 itself accompanies the executable.
00166 
00167 If distribution of executable or object code is made by offering
00168 access to copy from a designated place, then offering equivalent
00169 access to copy the source code from the same place counts as
00170 distribution of the source code, even though third parties are not
00171 compelled to copy the source along with the object code.
00172 
00173   4. You may not copy, modify, sublicense, or distribute the Program
00174 except as expressly provided under this License.  Any attempt
00175 otherwise to copy, modify, sublicense or distribute the Program is
00176 void, and will automatically terminate your rights under this License.
00177 However, parties who have received copies, or rights, from you under
00178 this License will not have their licenses terminated so long as such
00179 parties remain in full compliance.
00180 
00181   5. You are not required to accept this License, since you have not
00182 signed it.  However, nothing else grants you permission to modify or
00183 distribute the Program or its derivative works.  These actions are
00184 prohibited by law if you do not accept this License.  Therefore, by
00185 modifying or distributing the Program (or any work based on the
00186 Program), you indicate your acceptance of this License to do so, and
00187 all its terms and conditions for copying, distributing or modifying
00188 the Program or works based on it.
00189 
00190   6. Each time you redistribute the Program (or any work based on the
00191 Program), the recipient automatically receives a license from the
00192 original licensor to copy, distribute or modify the Program subject to
00193 these terms and conditions.  You may not impose any further
00194 restrictions on the recipients' exercise of the rights granted herein.
00195 You are not responsible for enforcing compliance by third parties to
00196 this License.
00197 
00198   7. If, as a consequence of a court judgment or allegation of patent
00199 infringement or for any other reason (not limited to patent issues),
00200 conditions are imposed on you (whether by court order, agreement or
00201 otherwise) that contradict the conditions of this License, they do not
00202 excuse you from the conditions of this License.  If you cannot
00203 distribute so as to satisfy simultaneously your obligations under this
00204 License and any other pertinent obligations, then as a consequence you
00205 may not distribute the Program at all.  For example, if a patent
00206 license would not permit royalty-free redistribution of the Program by
00207 all those who receive copies directly or indirectly through you, then
00208 the only way you could satisfy both it and this License would be to
00209 refrain entirely from distribution of the Program.
00210 
00211 If any portion of this section is held invalid or unenforceable under
00212 any particular circumstance, the balance of the section is intended to
00213 apply and the section as a whole is intended to apply in other
00214 circumstances.
00215 
00216 It is not the purpose of this section to induce you to infringe any
00217 patents or other property right claims or to contest validity of any
00218 such claims; this section has the sole purpose of protecting the
00219 integrity of the free software distribution system, which is
00220 implemented by public license practices.  Many people have made
00221 generous contributions to the wide range of software distributed
00222 through that system in reliance on consistent application of that
00223 system; it is up to the author/donor to decide if he or she is willing
00224 to distribute software through any other system and a licensee cannot
00225 impose that choice.
00226 
00227 This section is intended to make thoroughly clear what is believed to
00228 be a consequence of the rest of this License.
00229 
00230   8. If the distribution and/or use of the Program is restricted in
00231 certain countries either by patents or by copyrighted interfaces, the
00232 original copyright holder who places the Program under this License
00233 may add an explicit geographical distribution limitation excluding
00234 those countries, so that distribution is permitted only in or among
00235 countries not thus excluded.  In such case, this License incorporates
00236 the limitation as if written in the body of this License.
00237 
00238   9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time.  Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
00239 
00240 Each version is given a distinguishing version number.  If the Program
00241 specifies a version number of this License which applies to it and "any
00242 later version", you have the option of following the terms and conditions 
00243 either of that version or of any later version published by the Free Software 
00244 Foundation.  If the Program does not specify a version number of this License,
00245  you may choose any version ever published by the Free Software Foundation.
00246 
00247   10. If you wish to incorporate parts of the Program into other free
00248 programs whose distribution conditions are different, write to the author to 
00249 ask for permission.  For software which is copyrighted by the Free Software 
00250 Foundation, write to the Free Software Foundation; we sometimes make 
00251 exceptions for this.  Our decision will be guided by the two goals of 
00252 preserving the free status of all derivatives of our free software and of 
00253 promoting the sharing and reuse of software generally.
00254 
00255                             NO WARRANTY
00256 
00257   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
00258 THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN 
00259 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE 
00260 THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 
00261 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
00262 FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND 
00263 PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, 
00264 YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
00265 
00266   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
00267 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
00268 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 
00269 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
00270 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO 
00271 LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR 
00272 THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 
00273 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
00274 DAMAGES.
00275 
00276                      END OF TERMS AND CONDITIONS '
00277 */
00278 
00279 /*
00280   Change Log:
00281   $Log$
00282   Revision 8.6.2.1  2007/07/15 14:33:57  ron-fox
00283   Add emptyEnable/Disable to CAENcard.
00284 
00285   Revision 8.6  2006/05/15 14:29:45  ron-fox
00286   Little misc. changes..
00287 
00288   Revision 8.5  2006/04/05 11:24:53  ron-fox
00289   1. Commit changes since the restore from sourceforge's backups.
00290   2. Revert the CAENcard support... firmware 8.08 still makes wordcount
00291      errors.
00292 
00293   Revision 8.4  2005/08/24 11:15:46  ron-fox
00294   Improve CAENcard readout performance for non mapped devices.
00295 
00296   Revision 8.3  2005/08/15 21:49:32  ron-fox
00297   Support for the CAEN V1785 module.  This module is a weird dual
00298   range ADC.
00299 
00300   Revision 8.2  2005/06/24 11:30:36  ron-fox
00301   Bring the entire world onto the 8.2 line
00302 
00303   Revision 4.6  2005/05/24 11:08:00  ron-fox
00304   Minor commits and open 8.0-001 edit level
00305 
00306   Revision 4.5  2005/05/05 13:28:32  ron-fox
00307   Put vmetcl on top of the CVmeInterface peek/poke class so that
00308   it is independent of the VME interface module
00309 
00310   Revision 4.4  2004/12/21 18:08:55  ron-fox
00311   Finalize 8.0pre1
00312 
00313   Revision 4.3  2004/12/07 15:20:21  ron-fox
00314   - Fix some CVS errors with the wiener driver.
00315   - Re create the autotools based build for the wiener driver stuff.
00316   - Actually check that we can compile the stuff selecting the wiener
00317     vme device
00318 
00319   Revision 4.2  2004/11/16 15:24:48  ron-fox
00320   - Port to the gnu 3.x compiler set.
00321   - Integrate buid of tests.
00322   - Integrate build of docos.
00323 
00324   Revision 1.6  2004/11/16 15:23:28  ron-fox
00325   - Port -> gcc/g++ 3.x
00326   - Support integrated test building.
00327   - Support integrated doxygen docu7mentation building.
00328 
00329   Revision 1.5  2004/11/05 21:31:34  ron-fox
00330   Bring onto main line
00331 
00332   Revision 1.3.4.2  2004/08/17 20:38:09  ron-fox
00333   Fix error in #ifdef/#else without #endif in code to selectively enable
00334   the copying functionality.
00335 
00336   Revision 1.3.4.1  2004/08/17 09:00:54  ron-fox
00337   Use CopyIn again where it's possible.. the assumption is that
00338   everyone has a good spectrodaq!!!
00339 
00340   Revision 1.3  2004/01/14 17:45:09  ron-fox
00341   Remove code for spectrodaq copyin that
00342   crept back in by mistake.
00343 
00344   Revision 1.2  2003/12/03 18:12:48  ron-fox
00345   Fix stupid typo.
00346 
00347   Revision 1.1  2003/12/03 15:59:29  ron-fox
00348   Add CAENcard and associated documentation.
00349 
00350   Revision 3.9  2003/10/31 17:48:13  ron-fox
00351   correct bad call signature for DAQxxxBufPtr::CopyIn
00352 
00353   Revision 3.8  2003/09/19 19:53:34  ron-fox
00354   Add:
00355    - Statistics about event fix ups.
00356    - Access to a few more bits of SR1 and SR2.
00357 
00358   Revision 3.7  2003/09/16 12:15:09  ron-fox
00359   Fixed setVoltageThreshold to work regardless of the threshold mode (small or large).
00360 
00361   Revision 3.6  2003/08/14 17:57:47  ron-fox
00362   Add support for small threshold mode in modules up to date enough to implement it.  Note that we still need to modify the setthresholdvoltage function so that it understands what to do in the different pedestal modes.
00363 
00364   Revision 3.5  2003/06/19 19:09:17  ron-fox
00365   Rewrite to make both multi-crate safe and a little cleaner code.
00366   work around problems I'm seeing with word count field corruption.
00367 
00368   Revision 3.4  2003/06/06 11:40:11  ron-fox
00369   Remove some debug output now that everything works.
00370 
00371   Revision 3.3  2003/06/02 14:37:33  ron-fox
00372   Support multiple crates correctly.
00373 
00374 */
00375 
00376 static const char* Copyright= "(C) Copyright Michigan State University 2002, All rights reserved";
00377 
00378 #include <config.h>
00379 
00380 
00381 #include "CAENcard.h"
00382 #include <string>
00383 #include <unistd.h>
00384 
00385 #include <assert.h>
00386 #ifdef HAVE_STD_NAMESPACE
00387 using namespace std;
00388 #endif
00389 
00390 
00391 //   Convenience function for longword swapping.
00392 #define swaplong(n)  (((n >> 16) & 0xffff) | ((n & 0xffff) << 16))
00393 //
00394 
00395 #define VME_CRATE_SIZE      24  // Slots in a VME crate.
00396 
00397 #define CAEN_REGISTERSIZE   0x2000 // Size of CAEN Register set.
00398 #define CAEN_ROMSIZE        0x1000 // Size of CAEN ROM page.
00399 #define CAEN_ROMOFFSET      0x8000 // Offset from base of ROM page.
00400 
00401 
00402 // Bits we need in registers:
00403 
00404 // Threshold memory.
00405 
00406 #define KILLBIT  0x100          // Kill bit in threshold registers.
00407 
00408 // Bit Set/Clear 1 register:
00409 
00410 #define RESET       0x080
00411 #define SELADDR     0x010
00412 
00413 // Status register 1:
00414 
00415 
00416 #define DREADY      0x001
00417 #define GDREADY     0x002
00418 #define BUSY        0x004
00419 #define GBUSY       0x008
00420 
00421 
00422 // Bit Set/Clear 2 register.
00423 
00424 #define OFFLINE     0x002
00425 #define CLEARDATA   0x004
00426 #define KEEPOVER    0x008
00427 #define KEEPTHRESH  0x010
00428 #define KEEPINVALID 0x020
00429 #define COMMONSTOP  0x400
00430 #define STEPTHR     0x100
00431 #define AUTOIN      0x800
00432 #define EMPTY       0x1000
00433 #define SLIDESUB    0x2000
00434 #define ALLTRG      0x4000
00435 
00436 
00437 // Control register1:
00438 
00439 #define CTL1BLKEND   0x04
00440 #define CTL1PROGRST  0x10
00441 #define CTL1BERRENA  0x20
00442 #define CTL1ALIGN64  0x40
00443 
00444 
00445 // Multicast control register:
00446 
00447 #define MCSTFIRST    2
00448 #define MCSTLAST     1
00449 
00450 
00451 // Status register 2:
00452 
00453 #define SR2EMPTY     2          // MEB empty
00454 #define SR2FULL      4          // MEB full.
00455 
00456 
00457 // The structure below represents the CAEN register set:
00458 //
00459 
00460 struct Registers {
00461   unsigned long   Buffer[0x1000/sizeof(long)]; // 0x0000
00462   unsigned short  FirmwareRev;                 // 0x1000
00463   unsigned short  GeoAddress;                  // 0x1002
00464   unsigned short  MCSTAddress;                 // 0x1004
00465   unsigned short  BitSet1;                     // 0x1006
00466   unsigned short  BitClear1;                   // 0x1008
00467   unsigned short  InterruptLevel;              // 0x100a
00468   unsigned short  InterruptVector;             // 0x100c
00469   unsigned short  Status1;                     // 0x100e
00470   unsigned short  Control1;                    // 0x1010
00471   unsigned short  HighAddress;                 // 0x1012
00472   unsigned short  LowAddress;                  // 0x1014
00473   unsigned short  Reset;                       // 0x1016
00474   unsigned short  pad1;                        // 0x1018
00475   unsigned short  MCSTControl;                 // 0x101a
00476   unsigned short  pad2;                        // 0x101c
00477   unsigned short  pad3;                        // 0x101e
00478   unsigned short  EventTrigger;                // 0x1020
00479   unsigned short  Status2;                     // 0x1022
00480   unsigned short  EventCounterLow;             // 0x1024
00481   unsigned short  EventCounterHigh;            // 0x1026
00482   unsigned short  IncrementEvent;              // 0x1028
00483   unsigned short  IncrementOffset;             // 0x102a
00484   unsigned short  LoadTestRegister;            // 0x102c
00485   unsigned short  FCLRWindow;                  // 0x102e
00486   unsigned short  pad4;                        // 0x1030
00487   unsigned short  BitSet2;                     // 0x1032
00488   unsigned short  BitClear2;                   // 0x1034
00489   unsigned short  WMemoryTestAddress;          // 0x1036
00490   unsigned short  MemoryTestHigh;              // 0x1038
00491   unsigned short  MemoryTestLow;               // 0x103a
00492   unsigned short  CrateSelect;                 // 0x103c
00493   unsigned short  TestEventWrite;              // 0x103e
00494   unsigned short  EventCounterReset;           // 0x1040
00495   unsigned short  pad5[15];                    // 0x1042-105e
00496   unsigned short  TDCRange;                    // 0x1060
00497   unsigned short  pad7;                        // 0x1062
00498   unsigned short  RMemoryTestAddress;          // 0x1064
00499   unsigned short  pad8;                        // 0x1066
00500   unsigned short  SWComm;                      // 0x1068
00501   unsigned short  SlideConstant;               // 0x106a
00502   unsigned short  pad10;                       // 0x106c
00503   unsigned short  pad11;                       // 0x106e
00504   unsigned short  AAD;                         // 0x1070
00505   unsigned short  BAD;                         // 0x1072
00506   unsigned short  pad9[6];                     // 0x1074-107e
00507   unsigned short  Thresholds[32];              // 0x1080
00508   
00509 };
00510 #define QDCIPedestal TDCRange    // same register offsets.
00511 
00512 // The structure below represents the part of the board ROM
00513 // we care about... it holds a few chunks of useful info about
00514 // the board:
00515 
00516 struct ROM {
00517   unsigned short  pad1[0x26/sizeof(short)];  // 0x8000 - 0x8024
00518   unsigned short  OUIMSB;                    // 0x8026
00519   unsigned short  pad2;                      // 0x8028
00520   unsigned short  OUI;                       // 0x802a
00521   unsigned short  pad3;                      // 0x802c
00522   unsigned short  OUILSB;                    // 0x802e
00523   unsigned short  pad4;                      // 0x8030
00524   unsigned short  Version;                   // 0x8032
00525   unsigned short  pad5;                      // 0x8034
00526   unsigned short  BoardIdMSB;                // 0x8036
00527   unsigned short  pad6;                      // 0x8038
00528   unsigned short  BoardId;                   // 0x803a
00529   unsigned short  pad7;                      // 0x803c
00530   unsigned short  BoardIdLSB;                // 0x803e
00531   unsigned short  pad8[7];                   // 0x8040-0x804c
00532   unsigned short  Revision;                  // 0x804e
00533   unsigned short  pad9[0xb0/sizeof(short)];  // 0x8050 - 0x8100
00534   unsigned short  pad10[0xe00/sizeof(short)]; // 0x8100 - 0x8ffe
00535   unsigned short  pad11;                     // 0x8f00
00536   unsigned short  SerialMSB;                 // 0x8f02
00537   unsigned short  pad12;                     // 0x8f04
00538   unsigned short  SerialLSB;                 // 0x8f06
00539 };
00540 
00541 
00542 // Byte offset associated with a structure/field.
00543 
00544 
00545 #define Offset(structname, field)  \
00546 ((unsigned int)&(((structname*)0x0)->field))
00547 
00549 
00550 #define ShortOffset(structname, field) Offset(structname, field)/sizeof(short)
00551 #define LongOffset(structname, field)  Offset(structname, field)/sizeof(long)
00552 
00555 #ifdef HAVE_VME_MAPPING
00556 #define ReadBuffer   (((volatile Registers*)m_pModule)->Buffer[0])
00557 #else
00558 #define ReadBuffer   (m_pModule->peekl(LongOffset(Registers, Buffer)));
00559 #endif
00560 
00561 
00567 void
00568 CAENcard::ReadBufferBlock(int* pDest, Int_t nLongs)
00569 {
00570 #ifdef HAVE_VME_MAPPING
00571   for(int i = 0; i < nLongs; i++) {
00572     int Datum = ReadBuffer;
00573     *pDest++ = swaplong(Datum);
00574   }
00575 #else
00576   int* pd = pDest;
00577   m_pModule->readl(pd, LongOffset(Registers, Buffer), nLongs);
00578   for(int i =0; i < nLongs; i++) {
00579     *pDest++ = swaplong(*pDest);
00580   }
00581 #endif
00582 }
00583 
00584 
00613 CAENcard::CAENcard(int slotNum, int crateNum , 
00614                    bool Geo, long nBase) :
00615   m_nSlot(slotNum),
00616   m_nCrate(crateNum),
00617   m_fGeo(Geo),
00618   m_nBase(nBase),
00619   m_pModule(0),
00620   m_nFirmware(0)
00621 {
00622   assert(sizeof(Registers) == 0x10c0);    // else struct misdefined.
00623   assert(sizeof(ROM) == 0xf08);          // else struct misdefined.
00624   slotInit();
00625 }
00636 CAENcard::CAENcard(const CAENcard& card) :
00637   m_nSlot(card.m_nSlot),
00638   m_nCrate(card.m_nCrate),
00639   m_fGeo(card.m_fGeo),
00640   m_nBase(card.m_nBase),
00641   m_pModule(0),
00642   m_fSmallThresholds(false)
00643 {
00644   MapCard();                    // Map the card.
00645 }
00646 
00658 CAENcard& CAENcard::operator=(const CAENcard& card)
00659 {
00660   if(this != &card) {
00661     if(this->m_pModule) DestroyCard(); // Destroy old memory map.
00662     m_nSlot   = card.m_nSlot;
00663     m_nCrate = card.m_nCrate;
00664     m_fGeo   = m_fGeo;
00665     m_nBase  = card.m_nBase;
00666     MapCard();
00667   }
00668   return *this;
00669 }
00670 
00671 
00672 
00687 void 
00688 CAENcard::slotInit()
00689 {
00690 
00691   MapCard();
00692 
00693   reset();                      // clears the event count and buffer
00694   channelOn(-1);                // Enable all channels.
00695   setCrate(m_nCrate);           // Set the module's crate number.
00696   
00697   if(cardType() == 775) {       // Set defaults for a TDC:
00698     // set use common start mode
00699     // with thresholds at 14ns.
00700 
00701     commonStart();
00702     setRange(0xFF);
00703     setThreshold(-1, 0x19);
00704 
00705   }
00706   else if((cardType() == 785) || 
00707           (cardType() == 1785)) {       // Set the defaults for a Peak ADC:
00708       // thresholds to ~15mV 
00709 
00710     setThreshold(-1, 0x01);
00711 
00712   }
00713   else if((cardType() == 792) || (cardType() == 862)) { // Set defaults for a QDC:
00714 
00715       setThreshold(-1, 0);      // Maybe later default raise this??
00716   }
00717   
00718 
00719 }
00720 
00726 CAENcard::~CAENcard()
00727 {
00728   DestroyCard();
00729 }
00730 
00736 int 
00737 CAENcard::cardType()
00738 {
00739   return m_nCardType;
00740 }
00741 
00753 void 
00754 CAENcard::setCrate(int crateNum)
00755 {
00756 #ifdef HAVE_VME_MAPPING
00757   volatile Registers* pModule = (volatile Registers*)m_pModule;
00758   pModule->CrateSelect = crateNum & 0x0ff; // Bottom 8 bits only.
00759 #else
00760    m_pModule->pokew((0x0ff & m_pModule->peekw(ShortOffset(Registers,CrateSelect))),
00761                     ShortOffset(Registers,CrateSelect));
00762 #endif
00763 }
00764 
00772 int 
00773 CAENcard::getCrate()
00774 {
00775 #ifdef HAVE_VME_MAPPING
00776   volatile Registers* pModule = (volatile Registers*)m_pModule;
00777   return (pModule->CrateSelect & 0xff);
00778 #else
00779   return (m_pModule->peekw(ShortOffset(Registers, CrateSelect)) & 0xff);
00780 #endif
00781 
00782 }
00783 
00809 void 
00810 CAENcard::setThreshold(int ch, int threshold)
00811 {
00812   volatile Registers* pModule = (volatile Registers*)m_pModule;
00813   threshold = threshold & 0x00FF;
00814   
00815   if( ch < 0 ) {
00816     for(int i = 0; i < 32; i++) {
00817       setThreshold(i,threshold); // Set individual channel threshold
00818     }
00819   }
00820   else {
00821 #ifdef HAVE_VME_MAPPING
00822     Registers* pModule      = (Registers*)m_pModule;
00823     pModule->Thresholds[ch] = threshold |
00824                              (pModule->Thresholds[ch] & KILLBIT);
00825 #else
00826     int noffset = ShortOffset(Registers, Thresholds[ch]);
00827     int now     = m_pModule->peekw(noffset);
00828     now         = threshold | (now & KILLBIT);
00829     m_pModule->pokew(now, noffset);
00830 #endif
00831   }
00832 }
00833 
00846 void 
00847 CAENcard::setThresholdVoltage(int ch, double voltage)
00848 {
00849   if(m_fSmallThresholds) {
00850     setThreshold(ch,(int)(voltage*64.0));  
00851   }
00852   else {
00853     setThreshold(ch, (int)(voltage*8.0));
00854   }
00855 }
00856 
00864 void CAENcard::keepUnderThresholdData()
00865 {
00866   Bitset2(KEEPTHRESH);
00867 }
00868 
00873 void CAENcard::discardUnderThresholdData()
00874 {
00875   Bitclear2(KEEPTHRESH);
00876 
00877 }
00884 void CAENcard::keepOverflowData()
00885 {
00886   Bitset2(KEEPOVER);
00887 }
00888 
00894 void CAENcard::discardOverflowData()
00895 {
00896   Bitclear2(KEEPOVER);
00897 
00898 }
00899 
00907 void
00908 CAENcard::keepInvalidData() 
00909 { 
00910 
00911   if(cardType() == 775) {
00912     Bitset2(KEEPINVALID);
00913   }
00914   else {
00915     throw string("keepInvalidData - Module is not a V775 TDC");
00916   }
00917 }
00924 void 
00925 CAENcard::discardInvalidData()
00926 {
00927   if(cardType() == 775)
00928   {
00929     Bitclear2(KEEPINVALID);
00930   }
00931   else
00932   {
00933     throw string("discardInvalidData - Module is not a V775 TDC");
00934   }
00935 }
00941 void
00942 CAENcard::emptyEnable()
00943 {
00944         Bitset2(EMPTY);
00945 }
00952 void
00953 CAENcard::emptyDisable()
00954 {
00955         Bitclear2(EMPTY);
00956 }
00957 
00969 void CAENcard::commonStart()
00970 {
00971   //make sure that the card is a TDC and initialized
00972   if(cardType() == 775)
00973   {
00974     Bitclear2(COMMONSTOP);
00975   }
00976   else
00977   {
00978     throw string("commonStart()  - Module is not a V775 TDC");
00979   }
00980 }
00981 
00989 void
00990 CAENcard::commonStop()
00991 {
00992   //make sure that the card is a TDC and initialized
00993   if(cardType() == 775)
00994   {
00995     volatile Registers* pRegisters = (volatile Registers*)m_pModule;
00996     Bitset2(COMMONSTOP);
00997     
00998   }
00999   else
01000   {
01001     throw string("commonStop() - Module is not a V775 TDC");
01002   }
01003 }
01004 
01022 void
01023 CAENcard::setRange(int range)
01024 {
01025   //make sure that the card is a TDC
01026 
01027   if(cardType() == 775)
01028   {
01029     if(range > 0x001D && range < 0x0100)
01030     {
01031 #ifdef HAVE_VME_MAPPING
01032       volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01033       pRegisters->TDCRange  = (short int)range;
01034 #else
01035       m_pModule->pokew(range, ShortOffset(Registers, TDCRange));
01036 #endif
01037 
01038     }
01039     else
01040     {
01041       throw 
01042         string("setRange - TDC Range value must be in [0x1e,0xff");
01043     }
01044   }
01045   else
01046   {
01047     throw string("setRange - Module is not a V775 TDC");
01048   }
01049 }
01050 
01066 void 
01067 CAENcard::setPedestalCurrent(int ped)
01068 {
01069   //make sure that the card is a QDC
01070   int type = cardType();
01071   if((type == 792) || (type == 862))
01072   {
01073     ped = ped & 0xff;
01074 #ifdef HAVE_VME_MAPPING
01075     volatile Registers* pRegisters    = (volatile Registers*) m_pModule;
01076     pRegisters->QDCIPedestal = (ped); 
01077 #else
01078     m_pModule->pokew(ped, ShortOffset(Registers,QDCIPedestal));
01079 #endif
01080   }
01081   else
01082   {
01083     throw string("setPedestalCurrent - module is not a V792 or V862 QDC");
01084   }
01085 }
01093 void 
01094 CAENcard::cardOff()
01095 {
01096   Bitset2(OFFLINE);
01097 }
01098 
01102 void 
01103 CAENcard::cardOn()
01104 {
01105   Bitclear2(OFFLINE);
01106 }
01107 
01127 void CAENcard::channelOff(int ch)
01128 {
01129 
01130   if( ch < 0 ) {
01131     for( int i = 0; i < 32; ++i )
01132       channelOff(i);
01133   }
01134   else {
01135     if(ch < 32) {
01136 #ifdef HAVE_VME_MAPPING
01137        volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01138        pRegisters->Thresholds[ch] |= KILLBIT;   
01139 #else
01140       short thresh = m_pModule->peekw(ShortOffset(Registers,Thresholds[ch])) | KILLBIT;
01141       m_pModule->pokew(thresh, ShortOffset(Registers,Thresholds[ch]));
01142 #endif
01143     } else {
01144       throw string("channelOff - channel number must be in [0,31]");
01145     }
01146   }
01147 }
01148 
01164 void 
01165 CAENcard::channelOn(int ch)
01166 {
01167 
01168   if( ch < 0 ) {
01169     for( int i = 0; i < 32; ++i )
01170       channelOn(i);
01171   }
01172   else {
01173     if(ch < 32) {
01174 #ifdef HAVE_VME_MAPPING
01175        volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01176        pRegisters->Thresholds[ch] &= ~(KILLBIT);
01177 #else
01178       int thresh =  m_pModule->peekw(ShortOffset(Registers,Thresholds[ch])) & ~(KILLBIT);
01179        m_pModule->pokew(thresh, ShortOffset(Registers, Thresholds[ch]));
01180 #endif
01181     } 
01182     else {
01183       throw string("channelOn - channel number must be in [0,31]");
01184     }
01185   }
01186 
01187 }
01188 
01193 void 
01194 CAENcard::resetEventCounter()
01195 {
01196   // Any write triggers the reset!
01197 
01198 #ifdef HAVE_VME_MAPPING
01199   ((volatile Registers*)m_pModule)->EventCounterReset = 1;
01200 #else
01201    m_pModule->pokew(1, ShortOffset(Registers, EventCounterReset));
01202 #endif
01203 
01204 
01205   ((volatile Registers*)m_pModule)->EventCounterReset = 1;
01206 
01207 }
01208 
01213 void CAENcard::clearData()
01214 {
01215    Bitset2(CLEARDATA);
01216    Bitclear2(CLEARDATA);
01217 };
01218 
01233 void 
01234 CAENcard::reset()
01235 {
01236   Bitset1(RESET);
01237   Bitclear1(RESET);
01238 };
01239 
01247 bool 
01248 CAENcard::dataPresent()
01249 {
01250 #ifdef HAVE_VME_MAPPING
01251   volatile Registers* pReg = (volatile Registers*)m_pModule;
01252   return ((pReg->Status1 & DREADY) != 0);
01253 #else
01254   return ((m_pModule->peekw(ShortOffset(Registers, Status1))  & DREADY) != 0);
01255 #endif
01256 };
01257 
01270 int 
01271 CAENcard::readEvent(void* buf)
01272 {
01273 
01274   int* pBuf((int*)buf);
01275   if(dataPresent())
01276   {
01277     int n = 1;                  // Header at least is read.
01278     int  Header     = ReadBuffer;
01279     int* pHeader    = pBuf;     // To fix channel count.
01280     int  nRawChancnt= (Header >> 8) & 0x3f;
01281     *pBuf++         = swaplong(Header);
01282     if(0 && (getFirmware() >= 0x808) ) {        // Raw chancount reliable... NOT
01283       
01284       ReadBufferBlock(pBuf, nRawChancnt+1);
01285       return (nRawChancnt+2)*sizeof(long);
01286 
01287     } else {
01288       int datum;
01289       do {
01290         datum   = ReadBuffer;
01291         *pBuf++ = swaplong(datum);
01292         n++;
01293         datum = (datum >> 24) & 7;
01294       } while ( (datum == 0) && (n <= 34));
01295       if(datum != 4) {          // The trailer should be of type 4.
01296         cerr << " Data type in terminating long wrong: " << hex 
01297              <<datum << dec << endl;
01298         m_nInvalidTrailers++;
01299       } 
01300       if ((n-2) < nRawChancnt) m_nChancountHigh++;
01301       if ((n-2) > nRawChancnt) m_nChancountLow++;
01302       Header &= 0xffffC0ff;     // Channel count is sometimes wrong.
01303       Header |= ((n-2) << 8);   // this fixes it.
01304       *pHeader = swaplong(Header);
01305       m_nEvents++;              // Count an event taken.
01306       return n * sizeof(long);                  // Rely on the trailer!!
01307     }
01308   }else {
01309     // cerr << "Readout called but no data present\n";
01310     return 0;
01311   }
01312 }
01313 
01330 int 
01331 CAENcard::readEvent(DAQWordBuffer& wbuf, int offset)
01332 {
01333   int    localBuffer[32+2];     // 32 channels, + header + trailer.
01334   short* pBuf((short*)localBuffer); // Read here then copy.
01335 
01336 
01337   int n = readEvent(localBuffer);
01338   int nWords = n/sizeof(int);
01339   for(int i = 0; i < nWords; i++) {
01340     wbuf[offset] = *pBuf++;
01341     offset++;
01342   }
01343   return nWords;
01344   
01345 
01346 }
01347 
01362 int CAENcard::readEvent(DAQWordBufferPtr& wp)
01363 {
01364   // Patterned after the previous function:
01365 
01366   int localBuffer[32+200];
01367   short *pBuf((short*)localBuffer);
01368   int nbytes = readEvent(localBuffer); // Read to temp buffer.
01369   int nWords = nbytes / sizeof(short);
01370 #ifdef CLIENT_HAS_POINTER_COPYIN
01371   wp.CopyIn(localBuffer, 0, nWords);
01372   wp += nWords;
01373 #else
01374   for(int i =0; i < nWords; i++) {
01375     *wp = *pBuf++;
01376     ++wp;
01377   }
01378 #endif
01379   return nWords;
01380   
01381 };
01382 
01396 int 
01397 CAENcard::readEvent(DAQDWordBuffer& dwbuf, int offset)
01398 {
01399   int localBuffer[32+2];        // 32 chans + header + trailer.
01400   int nbytes = readEvent(localBuffer);
01401   int nlongs = nbytes/sizeof(long);
01402   int* pLocal(localBuffer);
01403   for(int i =0; i < nlongs; i++) {
01404     dwbuf[offset] = *pLocal++;
01405     offset++;
01406   }
01407   return nlongs;
01408 
01409 
01410 }
01411 
01422 int CAENcard::readEvent(DAQDWordBufferPtr& dwp)
01423 {
01424   int localBuffer[32+2];        // 32 chans + header +trailer.
01425   int nbytes  = readEvent(localBuffer);
01426   int nlongs  = nbytes/sizeof(long);
01427   int* pLocal(localBuffer);
01428   for(int i =0; i < nlongs; i++) {
01429     *dwp = *pLocal++;
01430     ++dwp;
01431   }
01432   return nlongs;
01433 
01434 
01435 }
01436 
01437 
01438 
01445 void CAENcard::setIped(int value)
01446 {
01447   setPedestalCurrent(value);
01448 }
01453 int CAENcard::getIped()
01454 {
01455   if((cardType() == 792) || (cardType() == 862)) {
01456 #ifdef HAVE_VME_MAPPING
01457     return ((volatile Registers*)m_pModule)->QDCIPedestal;
01458 #else
01459     return m_pModule->peekw(ShortOffset(Registers, QDCIPedestal));
01460 #endif
01461   } else {
01462     throw string("getIped - Module is not a V792 or V862 QDC");
01463   }
01464 
01465 }
01483 void CAENcard::MapCard()
01484 {
01485   //ensure that the slot and crate specified stay within bounds
01486 
01487    m_nCrate = m_nCrate & 0xff;  //not important enough to give an error for, just discard the extra
01488 
01489    if(m_nSlot > VME_CRATE_SIZE)
01490    {
01491       throw string("Invalid slot number specified to MapCard(). ");
01492    }
01493    
01494 
01495      //the card is not mapped yet, so do it
01496 
01497    void* fd;
01498 #ifndef HAVE_VME_MAPPING
01499    CVmeModule* pRom;
01500 #else
01501    ROM *pRom;
01502 #endif
01503    if( m_fGeo) {                // Geographical addressing...
01504 #ifndef HAVE_VME_MAPPING
01505       m_pModule = new CVmeModule(CVmeModule::geo, m_nSlot << 19, 
01506                                  CAEN_REGISTERSIZE, m_nCrate);
01507       pRom      = new CVmeModule(CVmeModule::geo, 
01508                                  ((long)m_nSlot << 19) + CAEN_ROMOFFSET,
01509                                  CAEN_ROMSIZE);
01510 #else
01511      fd   = CVMEInterface::Open(CVMEInterface::GEO, m_nCrate);
01512      m_pModule= (volatile unsigned short*) 
01513                    CVMEInterface::Map(fd, 
01514                                       (unsigned long)m_nSlot << 19, 
01515                                       CAEN_REGISTERSIZE);
01516      pRom     = (ROM*)
01517                       CVMEInterface::Map(fd,
01518                                          ((long)m_nSlot <<19) + 
01519                                          CAEN_ROMOFFSET,
01520                                          CAEN_ROMSIZE);
01521 #endif     
01522    }
01523    else {                                    // A32 addressing.
01524 #ifndef HAVE_VME_MAPPING 
01525      m_pModule = new CVmeModule(CVmeModule::a32d32, m_nBase,
01526                                 CAEN_REGISTERSIZE, m_nCrate);
01527      pRom      = new CVmeModule(CVmeModule::a32d32, m_nBase+CAEN_ROMOFFSET,
01528                                 CAEN_ROMSIZE);
01529       // The geographical address register must be programmed
01530      // in case the module or crate don't support geo.
01531 
01532      m_pModule->pokew(m_nSlot, ShortOffset(Registers, GeoAddress));
01533 #else
01534      fd = CVMEInterface::Open(CVMEInterface::A32, m_nCrate);
01535      m_pModule = (volatile unsigned short*) CVMEInterface::Map(fd,
01536                                                           m_nBase,
01537                                                  CAEN_REGISTERSIZE);
01538      pRom = (ROM*)CVMEInterface::Map(fd,
01539                                      m_nBase + CAEN_ROMOFFSET,
01540                                      CAEN_ROMSIZE);
01541       // The geographical address register must be programmed
01542      // in case the module or crate don't support geo.
01543 
01544      ((volatile Registers*)m_pModule)->GeoAddress = m_nSlot;
01545 #endif
01546    }
01547 
01548    // Get the module type from the PROM and unmap the prom,
01549    // as that's all we use it for:
01550 
01551 #ifndef HAVE_VME_MAPPING
01552    m_nCardType = (pRom->peekw(ShortOffset(ROM, BoardIdMSB)) & 0xff) << 16  |
01553                  (pRom->peekw(ShortOffset(ROM, BoardId))    & 0xff) << 8   |
01554                  (pRom->peekw(ShortOffset(ROM, BoardIdLSB)) & 0xff);
01555    m_nSerialno = (pRom->peekw(ShortOffset(ROM, SerialMSB))  & 0xff) << 8   |
01556                  (pRom->peekw(ShortOffset(ROM, SerialLSB))  & 0xff);
01557    m_nHardwareRev = pRom->peekw(ShortOffset(ROM, Revision));
01558    delete pRom;
01559 #else   
01560    m_nCardType = (pRom->BoardIdMSB & 0xff) << 16 |
01561                  (pRom->BoardId & 0xff)    <<  8 |
01562                  (pRom->BoardIdLSB & 0xff);
01563    m_nSerialno  = pRom->SerialMSB << 8 |
01564                  pRom->SerialLSB;
01565    m_nHardwareRev = pRom->Revision;
01566 
01567    // We can now unmap the prom:
01568    
01569    CVMEInterface::Unmap(fd, (void*)pRom, CAEN_ROMSIZE);
01570 #endif
01571    /* 
01572       To determine that the experimenter is not lying to us
01573       about how the VME is stuffed, we require that the module
01574       identifier be of a supported module type:
01575       V775, V785, V792, V862, or V1785 and that, for good measure,
01576       it's geographical address register match the slot
01577       the module is in.  For random data this should
01578       make a pretty miniscule chance that we'll be fooled
01579       by an empty slot. 1/32 * (1/2&24)
01580    */
01581 #ifndef HAVE_VME_MAPPING
01582    int nSlot = m_pModule->peekw(ShortOffset(Registers, GeoAddress)) & 0x1f;
01583 #else
01584    int nSlot = ((volatile Registers*)m_pModule)->GeoAddress & 0x1f;
01585 #endif
01586    
01587    if(!(
01588         ( m_nSlot  ==  nSlot )   &&
01589         ( (m_nCardType == 775) || 
01590           (m_nCardType == 785) || 
01591           (m_nCardType == 792) ||
01592           (m_nCardType == 862) ||
01593           (m_nCardType == 1785))
01594         ))   {   //either an invalid board or no board is present in this slot
01595 #ifndef HAVE_VME_MAPPING
01596    delete m_pModule;
01597 #else
01598      CVMEInterface::Unmap(fd, 
01599                           (void*)m_pModule, CAEN_REGISTERSIZE);
01600      
01601      CVMEInterface::Close(fd);
01602 #endif
01603      char buffer[128];
01604      sprintf(buffer, "Card in crate %d, slot %d is incompatible or missing %d\n",
01605              m_nCrate, m_nSlot, m_nCardType);
01606      throw string(buffer);
01607        
01608        string("Card is incompatable type or not inserted");
01609    }
01610    
01611    
01612    //  Now that we've accessed the card successfully,
01613    //  If the initial mapping was geographical, we need to
01614    //  re-map using our 'standard' address scheme.  Otherwise
01615    //  we won't be able to read the event buffer which makes
01616    //  the module hard to readout. Note that if !m_fGeo,
01617    //  we already have a non-geo map, so this section gets skipped.
01618 
01619    
01620    if(m_fGeo) {                              // Transition to A32...
01621      // Set the address registers of the module so that it will
01622      // recognize at m_nSlot << 24:
01623 #ifndef HAVE_VME_MAPPING
01624       m_pModule->pokew(m_nSlot, ShortOffset(Registers, HighAddress));
01625       m_pModule->pokew(0,       ShortOffset(Registers, LowAddress));
01626 #else
01627      ((volatile Registers*)m_pModule)->HighAddress = m_nSlot;
01628      ((volatile Registers*)m_pModule)->LowAddress  = 0;
01629 #endif
01630      // Enable address recognition based on the address registers
01631      // (bypass the rotary switches).
01632 
01633      Bitset1(SELADDR);
01634      
01635      //destroy GEO24 mmap and file descriptor
01636      // Now remap using A32 addressing:
01637 
01638 #ifndef HAVE_VME_MAPPING
01639      delete m_pModule;
01640      m_pModule = new CVmeModule(CVmeModule::a32d32, (long)m_nSlot << 24,
01641                               CAEN_REGISTERSIZE);
01642      
01643 #else
01644 
01645      CVMEInterface::Unmap(fd, (void*)m_pModule, CAEN_REGISTERSIZE);
01646      CVMEInterface::Close(fd);
01647 
01648      fd = CVMEInterface::Open(CVMEInterface::A32, m_nCrate);
01649      
01650      //create A32D16 mmap
01651      
01652      m_pModule = (volatile unsigned short *) 
01653      CVMEInterface::Map(fd, 
01654                         (long)m_nSlot << 24, 
01655                         CAEN_REGISTERSIZE);
01656 #endif
01657    }
01658    m_nFd = fd;                  // Save for destruction.
01659   
01660 }
01661 
01662 
01669 void CAENcard::DestroyCard()
01670 {
01671 #ifndef HAVE_VME_MAPPING
01672    delete m_pModule;
01673 #else
01674   CVMEInterface::Unmap(m_nFd, 
01675                        (void*)m_pModule,
01676                        CAEN_REGISTERSIZE);
01677   CVMEInterface::Close(m_nFd);
01678 #endif
01679 }
01680 
01684 int CAENcard::getFirmware() 
01685 {
01686   if (!m_nFirmware) {
01687 #ifndef HAVE_VME_MAPPING
01688     m_nFirmware = m_pModule->peekw(ShortOffset(Registers, FirmwareRev));
01689 #else
01690     m_nFirmware = ((Registers*)m_pModule)->FirmwareRev;
01691 #endif
01692   }
01693   return m_nFirmware;
01694 }
01700 void
01701 CAENcard::setFastClearWindow(int n)
01702 {
01703 #ifdef HAVE_VME_MAPPING
01704   Registers* pRegs = (Registers*)m_pModule;
01705   pRegs->FCLRWindow = n;
01706 #else
01707   m_pModule->pokew(n, ShortOffset(Registers, FCLRWindow));
01708 #endif
01709 }
01721 void
01722 CAENcard::enableSmallThresholds()
01723 {
01724   Bitset2(STEPTHR);
01725   m_fSmallThresholds = true;
01726 
01727 }
01738 void
01739 CAENcard::disableSmallThresholds()
01740 {
01741   Bitclear2(STEPTHR);
01742   m_fSmallThresholds = false;
01743 }
01744 
01745 
01759 void
01760 CAENcard::SetCBLTChainMembership(int cbltaddr,
01761                                  CAENcard::ChainMember where)
01762 {
01763   // Compute membership mask:
01764 
01765   int mask;
01766   switch (where) {
01767   case NotInChain:
01768     mask = 0;
01769     break;
01770   case FirstInChain:
01771     mask = MCSTFIRST;
01772     break;
01773   case LastInChain:
01774     mask = MCSTLAST;
01775     break;
01776   case IntermediateInChain:
01777     mask = MCSTFIRST | MCSTLAST;
01778     break;
01779   default:
01780     throw string("CAENcard::SetCBLTChainMembership: Invalid chain membership selector");
01781   }
01782 #ifdef HAVE_VME_MAPPING
01783   ((Registers*)m_pModule)->MCSTControl = mask;
01784   ((Registers*)m_pModule)->MCSTAddress = cbltaddr;
01785   ((Registers*)m_pModule)->Control1    = CTL1BERRENA;
01786 #else
01787   m_pModule->pokew(mask,       ShortOffset(Registers, MCSTControl));
01788   m_pModule->pokew(cbltaddr,   ShortOffset(Registers, MCSTAddress));
01789   m_pModule->pokew(CTL1BERRENA, ShortOffset(Registers, Control1));
01790 #endif
01791 }
01795 bool
01796 CAENcard::gdataPresent()
01797 {
01798 #ifdef HAVE_VME_MAPPING
01799   volatile Registers* pReg = (volatile Registers*)m_pModule;
01800   return ((pReg->Status1 & GDREADY) != 0);
01801 #else
01802   short mask = m_pModule->peekw(ShortOffset(Registers, Status1));
01803   return ((mask & GDREADY) != 0);
01804 #endif
01805 
01806 }
01810 bool
01811 CAENcard::Busy()
01812 {
01813 #ifdef HAVE_VME_MAPPING
01814   volatile Registers* pReg = (volatile Registers*)m_pModule;
01815   return ((pReg->Status1 & BUSY) != 0);
01816 #else
01817   short mask = m_pModule->peekw(ShortOffset(Registers, Status1));
01818   return ((mask & BUSY) != 0);
01819 #endif
01820 }
01825 bool
01826 CAENcard::gBusy()
01827 {
01828 #ifdef HAVE_VME_MAPPING
01829   volatile Registers* pReg = (volatile Registers*)m_pModule;
01830   return ((pReg->Status1 & GBUSY) != 0);
01831 #else
01832   short mask = m_pModule->peekw(ShortOffset(Registers, Status1));
01833   return ((mask & GBUSY) != 0);
01834 #endif
01835 }
01839 bool
01840 CAENcard::MEBFull()
01841 {
01842 #ifdef HAVE_VME_MAPPING
01843   volatile Registers* pReg = (volatile Registers*)m_pModule;
01844   return ((pReg->Status2 & SR2FULL) != 0);
01845 #else
01846   short mask = m_pModule->peekw(ShortOffset(Registers, Status2));
01847   return ((mask & SR2FULL) != 0);
01848 #endif
01849 }
01853 bool
01854 CAENcard::MEBEmpty()
01855 {
01856 #ifdef HAVE_VME_MAPPING
01857   volatile Registers* pReg = (volatile Registers*)m_pModule;
01858   return ((pReg->Status2 & SR2EMPTY) != 0);
01859 #else
01860   short mask = m_pModule->peekw(ShortOffset(Registers, Status2));
01861   return ((mask & SR2EMPTY) != 0);
01862 #endif
01863 }
01867 void
01868 CAENcard::ClearStatistics()
01869 {
01870   m_nInvalidTrailers = 0;
01871   m_nChancountHigh   = 0;
01872   m_nChancountLow    = 0;
01873   m_nEvents          = 0;
01874 }
01881 int
01882 CAENcard::InvalidTrailerCount() 
01883 {
01884   return m_nInvalidTrailers;
01885 }
01893 int
01894 CAENcard::ChannelsTooBigCount()
01895 {
01896   return m_nChancountHigh;
01897 }
01904 int
01905 CAENcard::ChannelsTooSmallCount()
01906 {
01907   return m_nChancountLow;
01908 }
01913 int
01914 CAENcard::EventCount()
01915 {
01916   return m_nEvents;
01917 }
01923 void
01924 CAENcard::Bitset1(short mask) 
01925 {
01926 #ifndef HAVE_VME_MAPPING
01927    m_pModule->pokew(mask, ShortOffset(Registers, BitSet1));
01928 #else
01929   volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01930   pRegisters->BitSet1   = mask;
01931 #endif   
01932 }
01938 void
01939 CAENcard::Bitclear1(short mask)
01940 {
01941 #ifndef HAVE_VME_MAPPING
01942    m_pModule->pokew(mask, ShortOffset(Registers, BitClear1));
01943 #else
01944   volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01945   pRegisters->BitClear1   = mask;
01946 #endif 
01947 }
01951 void
01952 CAENcard::Bitset2(short mask)
01953 {
01954 #ifndef HAVE_VME_MAPPING
01955    m_pModule->pokew(mask, ShortOffset(Registers, BitSet2));
01956 #else
01957   volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01958   pRegisters->BitSet2   = mask;
01959 #endif 
01960 }
01966 void
01967 CAENcard::Bitclear2(short mask)
01968 {
01969 #ifndef HAVE_VME_MAPPING
01970    m_pModule->pokew(mask, ShortOffset(Registers, BitClear2));
01971 #else
01972   volatile Registers* pRegisters = (volatile Registers*)m_pModule;
01973   pRegisters->BitClear2   = mask;
01974 #endif 
01975 }

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