00001 #include "V172X_Params.hh"
00002 #include "Message.hh"
00003 #include <exception>
00004 #include <stdexcept>
00005 #include <math.h>
00006
00007
00008
00009
00010
00011
00012
00013 const uint32_t max_14bit = 0x3FFF;
00014 const uint32_t acq_control_set = 0x28;
00015 const uint32_t channels_config_set = 0x10;
00016
00017 const int event_size_padding = 8;
00018 const int Mbyte = 1024*1024;
00019
00020 const uint16_t halfmax14 = 0x1FFF;
00021 const uint16_t halfmax16 = 0x7FFF;
00022 const uint32_t halfmax32 = 0x7FFFFFFF;
00023 using namespace std;
00024
00025 V172X_ChannelParams::V172X_ChannelParams() :
00026 ParameterList("V172X_ChannelParams",
00027 "Information about a single channel in a CAEN V172X digitizer")
00028 {
00029 RegisterParameter("enabled", enabled=true,
00030 "Is this channel active in the current run?");
00031 RegisterParameter("enable_trigger_source", enable_trigger_source=false,
00032 "Does this channel generat local trigger signals?");
00033 RegisterParameter("enable_trigger_out", enable_trigger_out=false,
00034 "Does this channel generate trigger out signals?");
00035 RegisterParameter("threshold", threshold = halfmax14,
00036 "The threshold (in counts) for the signal to trigger on");
00037 RegisterParameter("thresh_time_us", thresh_time_us = 0,
00038 "Time that the signal must be above/below threshold in order to generate a trigger");
00039 RegisterParameter("dc_offset", dc_offset = halfmax16,
00040 "DC offset (16 bit range) applied to the signal before digitizing");
00041 RegisterParameter("zs_polarity", zs_polarity = TP_FALLING, "Do we suppress the signal if it is below or above the zs_threshold?");
00042 RegisterParameter("zs_threshold",zs_threshold = halfmax14, "Threshold the signal must cross before it is considered to be non-zero");
00043 RegisterParameter("zs_thresh_time_us",zs_thresh_time_us = 0,"Time a signal must be above the zs_threshold before it counts");
00044 RegisterParameter("zs_pre_samps", zs_pre_samps = 10,
00045 "Number of samples to save before a ZLE removed block");
00046 RegisterParameter("zs_post_samps", zs_post_samps = 10,
00047 "Number of samples to save after a ZLE removed block");
00048
00049 RegisterParameter("label",label="x",
00050 "A descriptive label for the channel");
00051 }
00052
00053 V172X_BoardParams::V172X_BoardParams() :
00054 ParameterList("V172X_BoardParams",
00055 "Information about a single CAEN V172X Digitizer")
00056 {
00057 RegisterParameter("enabled", enabled = false,
00058 "Is this board active in this run?");
00059 RegisterParameter("address", address = 0xFFFF0000,
00060 "Address of the board on the VME crate (set in hardware)");
00061 RegisterParameter("link", link = 0,
00062 "Board optical link number");
00063 RegisterParameter("usb", usb = false,
00064 "Connect through USB instead of optical link?");
00065 RegisterParameter("chainindex", chainindex=0,
00066 "Order of board on a fiber daisy chain connection");
00067 RegisterParameter("id", id = -1, "Software id of the board");
00068 RegisterParameter("board_type", board_type = OTHER,
00069 "Specific model of digitizer (V1720, V1724, V1721)");
00070 RegisterParameter("nchans", nchans = MAXCHANS,
00071 "actual number of channels on this unit");
00072 RegisterParameter("v_full_scale", v_full_scale = 2,
00073 "Full scale range in voltage of the digitizer input");
00074 RegisterParameter("stupid_size_factor", stupid_size_factor = 1);
00075 RegisterParameter("sample_bits", sample_bits = 12,
00076 "Sampling depth of the ADC conversion");
00077 RegisterParameter("max_sample_rate", max_sample_rate = 250.,
00078 "Maximum number of samples recorded per microsecond");
00079 RegisterParameter("mem_size", mem_size = 1,
00080 "Maximum size of onboard buffer, in MSamples/channel");
00081 RegisterParameter("bytes_per_sample", bytes_per_sample = 2,
00082 "Number of aligned bytes needed for a single sample");
00083 RegisterParameter("event_size_bytes", event_size_bytes = 0,
00084 "Expected size of a single event in bytes");
00085 RegisterParameter("ns_per_clocktick", ns_per_clocktick = 8,
00086 "Time between each tick of the onboard trigger clock");
00087 RegisterParameter("enable_software_trigger", enable_software_trigger=true,
00088 "Can this board receive triggers from the VME plane (from the computer)?");
00089 RegisterParameter("enable_software_trigger_out",
00090 enable_software_trigger_out = true,
00091 "Does this board repeat VME triggers to the trigger-out signal?");
00092 RegisterParameter("enable_external_trigger", enable_external_trigger=true,
00093 "Does this board trigger on the trigger-in signal?");
00094 RegisterParameter("enable_external_trigger_out",
00095 enable_external_trigger_out = true,
00096 "Does this board repeat the trigger-in to trigger-out?");
00097 RegisterParameter("local_trigger_coincidence",local_trigger_coincidence = 0,
00098 "Number of channels after the first necessary to generate a trigger");
00099 RegisterParameter("pre_trigger_time_us", pre_trigger_time_us = 1,
00100 "Length of buffer time to to store before the trigger");
00101 RegisterParameter("post_trigger_time_us", post_trigger_time_us = 30,
00102 "Length of time after the trigger to store");
00103 RegisterParameter("downsample_factor", downsample_factor = 1,
00104 "No longer implemented in CAEN firmware; kept for compatibility only!");
00105 RegisterParameter("trigger_polarity", trigger_polarity = TP_FALLING,
00106 "Determines whether to generate trigger when the signal is above or below the trigger threshold");
00107 RegisterParameter("count_all_triggers", count_all_triggers = true,
00108 "Do we increment the trigger counter when overlapping triggers come in, or the buffer is full?");
00109 RegisterParameter("zs_type", zs_type = NONE,
00110 "Which type of zero suppression to use (should be NONE)");
00111 RegisterParameter("enable_trigger_overlap", enable_trigger_overlap = false,
00112 "Do we generate partial triggers if two come in too close to each other?");
00113 RegisterParameter("signal_logic", signal_logic = NIM,
00114 "Type of logic (NIM or TTL) for external signals");
00115 RegisterParameter("enable_test_pattern", enable_test_pattern = false,
00116 "Generate a triangle wave on the channels instead of measure real signals?");
00117
00118
00119
00120 for(int i=0; i<MAXCHANS; i++){
00121 char key[20];
00122 sprintf(key,"channel%d",i);
00123 RegisterParameter(key,channel[i]);
00124 }
00125 }
00126
00127 V172X_Params::V172X_Params() : ParameterList("V172X_Params")
00128 {
00129 RegisterParameter("align64", align64 = true,
00130 "Do we include an extra empty sample when using 64-bit size words?");
00131 RegisterParameter("trigger_timeout_ms", trigger_timeout_ms = 3000,
00132 "Time to wait for a trigger before timing out");
00133 RegisterParameter("max_mem_size", max_mem_size = 209715200,
00134 "Maximum amount of memory we're allowed to use for the raw event buffer");
00135 RegisterParameter("no_low_mem_warn",no_low_mem_warn = false,
00136 "Should we suppress the warning generated when the raw event buffer is full?");
00137 RegisterParameter("send_start_pulse",send_start_pulse = false,
00138 "Do we tell the digitizers to wait to start the event until a synchornize pulse is sent (true), or start immediately (false)");
00139 RegisterParameter("auto_trigger", auto_trigger = false,
00140 "Do we automatically generate a trigger if timeout occurrs?");
00141 RegisterParameter("vme_bridge_link", vme_bridge_link = 0,
00142 "VME bridge optical link number");
00143
00144
00145
00146 for(int i=0; i<nboards; i++){
00147 char key[20];
00148 sprintf(key,"board%d",i);
00149 RegisterParameter(key,board[i]);
00150 board[i].id = i;
00151 for(int j=0; j<board[i].MAXCHANS; j++){
00152 sprintf(key,"b%dch%d",i,j);
00153 board[i].channel[j].label = key;
00154 }
00155 }
00156 }
00157
00158 int V172X_BoardParams::UpdateBoardSpecificVariables()
00159 {
00160 switch(board_type){
00161 case V1724:
00162 max_sample_rate = 100.;
00163 sample_bits = 14;
00164 bytes_per_sample = 2;
00165 v_full_scale = 2.25;
00166 stupid_size_factor = 1;
00167 ns_per_clocktick = 10;
00168 break;
00169 case V1720:
00170 max_sample_rate = 250;
00171 sample_bits = 12;
00172 bytes_per_sample = 2;
00173 v_full_scale = 2;
00174 stupid_size_factor = 2;
00175 ns_per_clocktick = 8;
00176 break;
00177 case V1721:
00178 max_sample_rate = 1000;
00179 sample_bits = 8;
00180 bytes_per_sample = 1;
00181 v_full_scale = 2;
00182 stupid_size_factor = 1;
00183 ns_per_clocktick = 8;
00184 break;
00185 case V1751:
00186 max_sample_rate = 1000;
00187 sample_bits = 10;
00188 bytes_per_sample = 2;
00189 v_full_scale = 1;
00190 stupid_size_factor = 7;
00191 ns_per_clocktick = 4;
00192 break;
00193 default:
00194 return -1;
00195
00196 }
00197 return 0;
00198 }
00199
00200
00201
00202 double V172X_BoardParams::GetSampleRate() const
00203 {
00204
00205 return max_sample_rate;
00206 }
00207
00208 uint32_t V172X_BoardParams::GetPostNSamps() const
00209 {
00210 return (uint32_t)(post_trigger_time_us * GetSampleRate());
00211 }
00212
00213 uint32_t V172X_BoardParams::GetPreNSamps() const
00214 {
00215 return (uint32_t)(pre_trigger_time_us * GetSampleRate());
00216 }
00217
00218 uint32_t V172X_BoardParams::GetTotalNSamps() const
00219 {
00220 uint32_t total_nsamps = (uint32_t)
00221 (( pre_trigger_time_us + post_trigger_time_us ) * GetSampleRate());
00222 while( total_nsamps % (4/bytes_per_sample)) total_nsamps++;
00223
00224 return total_nsamps;
00225 }
00226
00227 uint32_t V172X_BoardParams::GetBufferCode() const
00228 {
00229 int max_samples = mem_size*Mbyte / bytes_per_sample;
00230 if(board_type == V1751)
00231 max_samples = (int)(Mbyte * (mem_size == 0x02 ? 1.835 : 14.4 ));
00232 uint32_t buffer_code = (uint32_t)floor(log2(max_samples / GetTotalNSamps()));
00233 if(buffer_code > 0xA)
00234 buffer_code = 0xA;
00235 return buffer_code;
00236 }
00237
00238 uint32_t V172X_BoardParams::GetCustomSizeSetting() const
00239 {
00240 if(board_type == V1751)
00241 return GetTotalNSamps()/stupid_size_factor;
00242 return GetTotalNSamps()*bytes_per_sample/
00243 ( sizeof(uint32_t) * stupid_size_factor);
00244 }
00245
00246 uint32_t V172X_BoardParams::GetPostTriggerSetting() const
00247 {
00248 const int latency = 10;
00249 if(board_type == V1751)
00250 return GetPostNSamps() / 16 - latency;
00251 return GetPostNSamps()/(2*stupid_size_factor) - latency;
00252
00253 }
00254
00255
00256 int V172X_BoardParams::GetTriggerIndex() const
00257 {
00258 return GetPreNSamps();
00259 }
00260
00261 uint64_t V172X_BoardParams::GetTimestampRange() const
00262 {
00263 return 0x7fffffff * ns_per_clocktick;
00264 }
00265
00266 int V172X_Params::GetEnabledBoards()
00267 {
00268 enabled_boards = 0;
00269 for(int i=0; i<nboards; i++)
00270 if(board[i].enabled) enabled_boards++;
00271 return enabled_boards;
00272 }
00273
00274 int V172X_Params::GetEnabledChannels()
00275 {
00276 enabled_boards = 0;
00277 enabled_channels = 0;
00278 for(int i=0; i<nboards; i++){
00279 if(!board[i].enabled) continue;
00280 enabled_boards++;
00281 for(int j=0; j<board[i].nchans; j++){
00282 if(board[i].channel[j].enabled) enabled_channels++;
00283 }
00284 }
00285 return enabled_channels;
00286 }
00287
00288
00289 int V172X_Params::GetEventSize()
00290 {
00291 enabled_boards = 0;
00292 enabled_channels = 0;
00293 event_size_bytes = 0;
00294
00295 for(int i=0; i<nboards; i++){
00296 if(!board[i].enabled) continue;
00297 enabled_boards++;
00298 board[i].event_size_bytes = event_size_padding + 16;
00299 for(int j =0; j<board[i].nchans; j++){
00300 if(board[i].channel[j].enabled){
00301 enabled_channels++;
00302 board[i].event_size_bytes += ( board[i].GetTotalNSamps() *
00303 board[i].bytes_per_sample )
00304 + (board[i].zs_type == ZLE ? 8 : 0 );
00305 }
00306 }
00307 event_size_bytes += board[i].event_size_bytes;
00308 }
00309
00310 return event_size_bytes;
00311 }
00312
00313 std::ostream& operator<<(std::ostream& out, const SIGNAL_LOGIC& logic)
00314 {
00315 if(logic==NIM)
00316 return out<<"NIM";
00317 else
00318 return out<<"TTL";
00319 }
00320
00321 std::ostream& operator<<(std::ostream& out, const ZERO_SUPPRESSION_TYPE& zs)
00322 {
00323 if(zs == NONE)
00324 return out<<"NONE";
00325 else if(zs == ZS_INT)
00326 return out<<"ZS_INT";
00327 else if(zs == ZLE)
00328 return out<<"ZLE";
00329 else
00330 return out<<"ZS_AMP";
00331 }
00332
00333 std::ostream& operator<<(std::ostream& out, const TRIGGER_POLARITY& pol)
00334 {
00335 if(pol == TP_RISING)
00336 return out<<"TP_RISING";
00337 else
00338 return out<<"TP_FALLING";
00339 }
00340
00341 std::ostream& operator<<(std::ostream& out, const BOARD_TYPE& type)
00342 {
00343 if(type == V1724)
00344 return out<<"V1724";
00345 else if (type == V1720)
00346 return out<<"V1720";
00347 else if (type == V1721)
00348 return out<<"V1721";
00349 else if (type == V1751)
00350 return out<<"V1751";
00351 else
00352 return out<<"OTHER";
00353 }
00354
00355 std::istream& operator>>(std::istream& in, SIGNAL_LOGIC &logic)
00356 {
00357 std::string temp;
00358 in>>temp;
00359 if(temp == "NIM" || temp == "nim")
00360 logic = NIM;
00361 else if(temp == "TTL" || temp == "ttl")
00362 logic = TTL;
00363 else{
00364 Message e(EXCEPTION);
00365 e<<temp<<" is not a valid value for SIGNAL_LOGIC"<<std::endl;
00366 throw std::invalid_argument(e.str());
00367 }
00368 return in;
00369 }
00370
00371 std::istream& operator>>(std::istream& in, ZERO_SUPPRESSION_TYPE &zs)
00372 {
00373 std::string temp;
00374 in>>temp;
00375 if(temp == "NONE" || temp == "none")
00376 zs = NONE;
00377 else if(temp == "ZS_INT" || temp == "zs_int")
00378 zs = ZS_INT;
00379 else if(temp == "ZLE" || temp == "zle")
00380 zs = ZLE;
00381 else if(temp == "ZS_AMP" || temp == "zs_amp")
00382 zs = ZS_AMP;
00383 else{
00384 Message e(EXCEPTION);
00385 e<<temp<<" is not a valid value for ZERO_SUPPRESSION_TYPE"<<std::endl;
00386 throw std::invalid_argument(e.str());
00387 }
00388 return in;
00389 }
00390
00391 std::istream& operator>>(std::istream& in, TRIGGER_POLARITY &pol)
00392 {
00393 std::string temp;
00394 in>>temp;
00395 if(temp == "TP_RISING" || temp == "tp_rising")
00396 pol = TP_RISING;
00397 else if(temp == "TP_FALLING" || temp == "tp_falling")
00398 pol = TP_FALLING;
00399 else{
00400 Message e(EXCEPTION);
00401 e<<temp<<" is not a valid value for TRIGGER_POLARITY"<<std::endl;
00402 throw std::invalid_argument(e.str());
00403 }
00404 return in;
00405 }
00406
00407 std::istream& operator>>(std::istream& in, BOARD_TYPE& type)
00408 {
00409 std::string temp;
00410 in>>temp;
00411 if(temp == "V1724")
00412 type = V1724;
00413 else if(temp == "V1720")
00414 type = V1720;
00415 else if (temp == "V1721")
00416 type = V1721;
00417 else if (temp == "V1751")
00418 type = V1751;
00419 else if (temp == "OTHER")
00420 type = OTHER;
00421 else{
00422 type = OTHER;
00423 Message e(EXCEPTION);
00424 e<<temp<<" is not a valid value for BOARD_TYPE"<<std::endl;
00425 throw std::invalid_argument(e.str());
00426 }
00427 return in;
00428 }