From 11875af9f98d1c1017609ece4e5d426f43a8624b Mon Sep 17 00:00:00 2001 From: "Ryan@Debain10" Date: Tue, 15 Mar 2022 14:38:58 -0400 Subject: [PATCH] updated to PixieSDK3.3. pixieDAQ can get ADC trace --- Makefile | 4 +- Pixie16.config | 19 +- Pixie16Class.cpp | 55 +-- Pixie16Class.h | 5 +- example.cpp | 777 ++++++++++++++++++++++++++------------- example_3.2.cpp | 917 +++++++++++++++++++++++++++++++++++++++++++++++ pixieDAQ.cpp | 59 ++- pixieDAQ.h | 15 +- test.cpp | 31 +- test_ryan.set | 12 +- 10 files changed, 1582 insertions(+), 312 deletions(-) create mode 100644 example_3.2.cpp diff --git a/Makefile b/Makefile index 9069a88..a3a6a50 100644 --- a/Makefile +++ b/Makefile @@ -30,9 +30,11 @@ LIBS = $(APIBASE)libPixie16Api.so $(APIBASE)libPixieSDK.a $(PLXBASE)PlxApi.a all: test example pixieDAQ example : example.o + @echo "-------- making example" $(CC) $(INCFLAGS) example.o $(LIBS) -o example example.o : example.cpp + @echo "-------- making example.o" $(CC) $(CFLAGS) $(INCFLAGS) example.cpp @@ -57,7 +59,7 @@ pixieDAQ : pixieDAQ.o Pixie16Class.o pixieDict.o pixieDAQ.o : pixieDAQ.cpp pixieDAQ.h @echo "--------- creating pcm " - @rootcling -f pixieDict.cxx -c pixieDAQ.h pixieDAQLinkDef.h + @rootcling -f pixieDict.cxx -c pixieDAQ.h -p $(INCFLAGS) pixieDAQLinkDef.h @echo "--------- creating pixieDAQ.o" $(CC) $(CFLAGS) $(INCFLAGS) pixieDAQ.cpp Pixie16Class.cpp pixieDict.cxx $(ROOT_FLAG) diff --git a/Pixie16.config b/Pixie16.config index 776b693..db56e99 100644 --- a/Pixie16.config +++ b/Pixie16.config @@ -9,7 +9,7 @@ #This must start at 2 and proceed sequentially at the moment # slot modID fpgaID S 2 0 25 -S 3 1 25 +#S 3 1 25 ########################################################################################################## ## FPGA Files ID ## @@ -19,11 +19,18 @@ S 3 1 25 ########################################################################################################## #250MHz 16-bit -F 25 0 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/firmware/syspixie16_revfgeneral_adc250mhz_r33339.bin -F 25 1 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/firmware/fippixie16_revfgeneral_12b250m_r42081.bin -F 25 2 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/dsp/Pixie16DSP_revfgeneral_12b250m_r41847.ldr -F 25 3 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/dsp/Pixie16DSP_revfgeneral_12b250m_r41847.var -F 25 4 /usr/opt/Pixie16/Pixie-16_FSU_Custom_Firmware_06022020/Configuration/Pixie16_FSU_Sample_Setup.set +F 25 0 /usr/opt/Pixie16/pixie16_revf_general_16b250m_35921_2017-01-09/firmware/syspixie16_revfgeneral_adc250mhz_r33339.bin +F 25 1 /usr/opt/Pixie16/pixie16_revf_general_16b250m_35921_2017-01-09/firmware/fippixie16_revfgeneral_16b250m_r36563.bin +F 25 2 /usr/opt/Pixie16/pixie16_revf_general_16b250m_35921_2017-01-09/dsp/Pixie16DSP_revfgeneral_16b250m_r35921.ldr +F 25 3 /usr/opt/Pixie16/pixie16_revf_general_16b250m_35921_2017-01-09/dsp/Pixie16DSP_revfgeneral_16b250m_r35921.var +F 25 4 /home/ryan/Pixie16/ryan/test_ryan.set + +#250MHz 12-bit +F 12 0 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/firmware/syspixie16_revfgeneral_adc250mhz_r33339.bin +F 12 1 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/firmware/fippixie16_revfgeneral_12b250m_r42081.bin +F 12 2 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/dsp/Pixie16DSP_revfgeneral_12b250m_r41847.ldr +F 12 3 /usr/opt/Pixie16/pixie16_revf_general_12b250m_41847_2019-05-18/dsp/Pixie16DSP_revfgeneral_12b250m_r41847.var +F 12 4 /home/ryan/Pixie16/ryan/test_ryan.set ######################################################################################################################## #120 space buffer limit diff --git a/Pixie16Class.cpp b/Pixie16Class.cpp index d4de07f..71f69f7 100644 --- a/Pixie16Class.cpp +++ b/Pixie16Class.cpp @@ -39,32 +39,30 @@ Pixie16::Pixie16(){ isRunning = false; retval = 0; - if( LoadConfigFile() == 0 ) { - retval = -1; - return; - } - CheckDriver(); if( retval > 0 ) CheckHardware(); if( retval > 0 ){ - LoadConfigFile(""); - BootDigitizers(); + LoadConfigFile(); + + if( retval > 0 ) { + BootDigitizers(); - nFIFOWords = 0; - ExtFIFO_Data = NULL; - Statistics = NULL; + nFIFOWords = 0; + ExtFIFO_Data = NULL; + Statistics = NULL; + + data = new DataBlock(); + nextWord = 0; - data = new DataBlock(); - nextWord = 0; + } } } Pixie16::~Pixie16(){ - retval = Pixie16ExitSystem(NumModules); - CheckError("Pixie16ExitSystem"); + CloseDigitizers(); delete PXISlotMap; delete ch2ns; @@ -82,7 +80,7 @@ Pixie16::~Pixie16(){ } -bool Pixie16::LoadConfigFile(bool verbose, std::string fileName){ +void Pixie16::LoadConfigFile(bool verbose, std::string fileName){ /************************************************************ * this method is copy and modified from J.M. Allmond (ORNL) @@ -110,7 +108,8 @@ bool Pixie16::LoadConfigFile(bool verbose, std::string fileName){ if ((fprconfig = fopen(fileName.c_str(), "r")) == NULL) { fprintf(stderr, "Error, cannot open input file %s\n", fileName.c_str()); - return false; + retval = -1; + return ; } NumModules = 0; @@ -149,7 +148,8 @@ bool Pixie16::LoadConfigFile(bool verbose, std::string fileName){ break; }else { printf("Error in reading %s : bad id or format\n", fileName.c_str()); - return -1; + retval = -2; + return; } }else if(line[i]=='\n'){ if(verbose) printf("\n"); @@ -171,10 +171,11 @@ bool Pixie16::LoadConfigFile(bool verbose, std::string fileName){ DSPParFile = new char* [NumModules]; DSPVarFile = new char* [NumModules]; - OfflineMode = 0; BootPattern = 0x7F; + ch2ns = new unsigned short [NumModules]; + for ( int i = 0 ; i < NumModules ; i++){ PXISlotMap[i] = tempPXISlotMap[i]; @@ -202,7 +203,7 @@ bool Pixie16::LoadConfigFile(bool verbose, std::string fileName){ printf(" DSP Par : %s \n", DSPParFile[i]); } - return true; + retval = 1; } int Pixie16::CheckError(std::string operation){ @@ -258,7 +259,8 @@ void Pixie16::GetDigitizerInfo(unsigned short modID){ unsigned int ModSerNum; unsigned short ModADCBits; unsigned short ModADCMSPS; - retval = Pixie16ReadModuleInfo(modID, &ModRev, &ModSerNum, &ModADCBits, &ModADCMSPS); + unsigned short numChannels; + retval = Pixie16ReadModuleInfo(modID, &ModRev, &ModSerNum, &ModADCBits, &ModADCMSPS, &numChannels); if( CheckError("Pixie16ReadModuleInfo") < 0 ) return ; @@ -267,6 +269,7 @@ void Pixie16::GetDigitizerInfo(unsigned short modID){ printf(" Serial Num : %d \n", ModSerNum); printf(" ADC Bits : %d \n", ModADCBits); printf("ADC sampling rate : %d \n", ModADCMSPS); + printf(" # channels : %d \n", numChannels); ch2ns[modID] = 1000/ModADCMSPS; @@ -307,6 +310,10 @@ void Pixie16::BootDigitizers(){ } +void Pixie16::CloseDigitizers(){ + retval = Pixie16ExitSystem(NumModules); + CheckError("Pixie16ExitSystem"); +} void Pixie16::AdjustOffset(){ @@ -608,9 +615,9 @@ void Pixie16::PrintChannelAllSettings(unsigned short modID, unsigned short ch){ void Pixie16::PrintChannelsMainSettings(unsigned short modID){ - printf("====+=====+======+========+========+===========+==========+==========+==========+========+========+=========+======+====== \n"); - printf(" ch | En | Gain | Trig_L | Trig_G | Threshold | Polarity | Energy_L | Energy_G | Tau | Trace | Trace_d | Voff | BL \n"); - printf("----+-----+------+--------+--------+-----------+----------+----------+----------+--------+--------+---------+------+------ \n"); + printf("====+=====+======+========+========+===========+==========+==========+==========+========+========+=========+=======+====== \n"); + printf(" ch | En | Gain | Trig_L | Trig_G | Threshold | Polarity | Energy_L | Energy_G | Tau | Trace | Trace_d | Voff | BL \n"); + printf("----+-----+------+--------+--------+-----------+----------+----------+----------+--------+--------+---------+-------+------ \n"); for( int ch = 0; ch < 16; ch ++){ printf(" %2d |", ch); printf(" %3s |", GetChannelOnOff(modID, ch) ? "On" : "Off" ); @@ -629,7 +636,7 @@ void Pixie16::PrintChannelsMainSettings(unsigned short modID){ printf(" %7s |", "Off"); printf(" %7s |", "Off"); } - printf(" %4.2f |", GetChannelVOffset(modID, ch)); + printf(" %5.2f |", GetChannelVOffset(modID, ch)); printf(" %4.2f %% \n", GetChannelBaseLinePrecent(modID, ch)); } } diff --git a/Pixie16Class.h b/Pixie16Class.h index bf1343a..2e6aaff 100644 --- a/Pixie16Class.h +++ b/Pixie16Class.h @@ -43,7 +43,7 @@ enum MOD_CSRB_BIT{ }; class Pixie16 { - + private: unsigned short NumCrates; unsigned short NumModules; @@ -88,13 +88,14 @@ public: bool IsRunning() {return isRunning;} ///======================== startup - bool LoadConfigFile( bool verbose = false, std::string fileName = "Pixie16.config"); + void LoadConfigFile( bool verbose = false, std::string fileName = "Pixie16.config"); void CheckDriver(); void CheckHardware(); void GetDigitizerInfo(unsigned short modID); void BootDigitizers(); + void CloseDigitizers(); unsigned short GetCh2ns(unsigned short modID) {return ch2ns[modID];} diff --git a/example.cpp b/example.cpp index ec75d63..a14798d 100644 --- a/example.cpp +++ b/example.cpp @@ -42,7 +42,6 @@ #include #include - #include struct LOG { @@ -71,14 +70,31 @@ struct LOG { std::string datetime_; }; +struct firmware_spec { + unsigned int version; + int revision; + int adc_msps; + int adc_bits; + + firmware_spec() : version(0), revision(0), adc_msps(0), adc_bits(0) {} +}; + struct module_config { - unsigned short slot; - unsigned short number; std::string com_fpga_config; - std::string sp_fpga_config; std::string dsp_code; std::string dsp_par; std::string dsp_var; + std::string sp_fpga_config; + unsigned int serial_number; + unsigned short adc_bit_resolution; + unsigned short adc_sampling_frequency; + unsigned short number; + unsigned short number_of_channels; + unsigned short revision; + unsigned short slot; + firmware_spec fw; + unsigned short has_worker_cfg; + fifo_worker_config worker_config; }; typedef std::vector module_configs; @@ -93,12 +109,7 @@ struct configuration { std::string generate_filename(const unsigned int& module_number, const std::string& type, const std::string& ext) { -#ifndef LEGACY_EXAMPLE - static const std::string file_prefix = "pixie16api-module"; -#else - static const std::string file_prefix = "pixie16app-module"; -#endif - return file_prefix + std::to_string(module_number) + "-" + type + "." + ext; + return "pixie16api-module" + std::to_string(module_number) + "-" + type + "." + ext; } void verify_json_module(const nlohmann::json& mod) { @@ -122,6 +133,25 @@ void verify_json_module(const nlohmann::json& mod) { if (!mod["fpga"].contains("fippi") || !mod["fpga"].contains("sys")) { throw std::invalid_argument("Missing fpga firmware definition (fippi or sys)."); } + + if (mod.contains("fw")) { + if (!mod["fw"].contains("version") || !mod["fw"].contains("revision") || + !mod["fw"].contains("adc_msps") || !mod["fw"].contains("adc_bits")) { + throw std::invalid_argument( + "Missing firmware (fw) definition (version, revision, adc_msps or adc_bits)."); + } + } + + if (mod.contains("worker")) { + if (!mod["worker"].contains("bandwidth_mb_per_sec") || !mod["worker"].contains("buffers") || + !mod["worker"].contains("dma_trigger_level_bytes") || + !mod["worker"].contains("hold_usecs") || !mod["worker"].contains("idle_wait_usecs") || + !mod["worker"].contains("run_wait_usecs")) { + throw std::invalid_argument( + "Missing worker fifo (worker) definition (bandwidth_mb_per_sec, buffers, " + "dma_trigger_level_bytes, hold_usecs, idle_wait_usecs, run_wait_usecs)."); + } + } } void read_config(const std::string& config_file_name, configuration& cfg) { @@ -151,6 +181,24 @@ void read_config(const std::string& config_file_name, configuration& cfg) { mod_cfg.dsp_code = module["dsp"]["ldr"]; mod_cfg.dsp_par = module["dsp"]["par"]; mod_cfg.dsp_var = module["dsp"]["var"]; + if (module.contains("fw")) { + mod_cfg.fw.version = module["fw"]["version"]; + mod_cfg.fw.revision = module["fw"]["revision"]; + mod_cfg.fw.adc_msps = module["fw"]["adc_msps"]; + mod_cfg.fw.adc_bits = module["fw"]["adc_bits"]; + } + if (module.contains("worker")) { + mod_cfg.worker_config.bandwidth_mb_per_sec = module["worker"]["bandwidth_mb_per_sec"]; + mod_cfg.worker_config.buffers = module["worker"]["buffers"]; + mod_cfg.worker_config.dma_trigger_level_bytes = + module["worker"]["dma_trigger_level_bytes"]; + mod_cfg.worker_config.hold_usecs = module["worker"]["hold_usecs"]; + mod_cfg.worker_config.idle_wait_usecs = module["worker"]["idle_wait_usecs"]; + mod_cfg.worker_config.run_wait_usecs = module["worker"]["run_wait_usecs"]; + mod_cfg.has_worker_cfg = 1; + } else { + mod_cfg.has_worker_cfg = 0; + } cfg.modules.push_back(mod_cfg); } } @@ -158,7 +206,11 @@ void read_config(const std::string& config_file_name, configuration& cfg) { bool verify_api_return_value(const int& val, const std::string& func_name, const bool& print_success = true) { if (val < 0) { - std::cout << LOG("ERROR") << func_name << " failed with Error Code " << val << std::endl; + std::string msg; + msg.resize(1024); + PixieGetReturnCodeText(val, &msg[0], msg.size()); + std::cout << LOG("ERROR") << func_name << " failed with code " << val + << " and message: " << msg << std::endl; return false; } if (print_success) @@ -166,42 +218,47 @@ bool verify_api_return_value(const int& val, const std::string& func_name, return true; } -bool output_statistics_data(const unsigned short& mod_num, const std::string& type) { -#ifndef LEGACY_EXAMPLE +bool output_statistics_data(const module_config& mod, const std::string& type) { std::vector stats(Pixie16GetStatisticsSize(), 0); -#else - std::vector stats(N_DSP_PAR - DSP_IO_BORDER, 0); -#endif - if (!verify_api_return_value(Pixie16ReadStatisticsFromModule(stats.data(), mod_num), + if (!verify_api_return_value(Pixie16ReadStatisticsFromModule(stats.data(), mod.number), "Pixie16ReadStatisticsFromModule", false)) return false; - std::ofstream bin_output(generate_filename(mod_num, type, "bin"), + std::ofstream bin_output(generate_filename(mod.number, type, "bin"), std::ios::binary | std::ios::out); bin_output.write(reinterpret_cast(stats.data()), sizeof(unsigned int) * stats.size()); bin_output.close(); - std::ofstream csv_output(generate_filename(mod_num, type, "csv"), std::ios::out); - csv_output << "channel,real_time,live_time,input_count_rate,output_count_rate" << std::endl; + std::ofstream csv_output(generate_filename(mod.number, type, "csv"), std::ios::out); + csv_output + << "channel,real_time,live_time,input_counts,input_count_rate,output_counts,output_count_rate" + << std::endl; + auto real_time = Pixie16ComputeRealTime(stats.data(), mod.number); - auto real_time = Pixie16ComputeRealTime(stats.data(), mod_num); + std::cout << LOG("INFO") << "Begin Statistics for Module " << mod.number << std::endl; + for (unsigned int chan = 0; chan < mod.number_of_channels; chan++) { + auto live_time = Pixie16ComputeLiveTime(stats.data(), mod.number, chan); + auto icr = Pixie16ComputeInputCountRate(stats.data(), mod.number, chan); + auto ocr = Pixie16ComputeOutputCountRate(stats.data(), mod.number, chan); - std::cout << LOG("INFO") << "Begin Statistics for Module " << mod_num << std::endl; - std::cout << LOG("INFO") << "Real Time: " << real_time << std::endl; - for (unsigned int chan = 0; chan < NUMBER_OF_CHANNELS; chan++) { - auto live_time = Pixie16ComputeLiveTime(stats.data(), mod_num, chan); - auto icr = Pixie16ComputeInputCountRate(stats.data(), mod_num, chan); - auto ocr = Pixie16ComputeOutputCountRate(stats.data(), mod_num, chan); + nlohmann::json json_stats = { + {"module", mod.number}, {"channel", chan}, {"real_time", real_time}, + {"live_time", live_time}, {"icr", icr}, {"ocr", ocr}, + }; - std::cout << LOG("INFO") << "Channel " << chan << " LiveTime: " << live_time << std::endl; - std::cout << LOG("INFO") << "Channel " << chan << " Input Count Rate: " << icr << std::endl; - std::cout << LOG("INFO") << "Channel " << chan << " Output Count Rate: " << ocr - << std::endl; + auto ic = Pixie16ComputeRawInputCount(stats.data(), mod.number, chan); + auto oc = Pixie16ComputeRawOutputCount(stats.data(), mod.number, chan); - csv_output << chan << "," << real_time << "," << live_time << "," << icr << "," << ocr - << std::endl; + json_stats["raw_input_count"] = ic; + json_stats["raw_output_count"] = oc; + + csv_output << chan << "," << real_time << "," << live_time << "," << ic << "," << icr << "," + << oc << "," << ocr << std::endl; + + std::cout << LOG("INFO") << json_stats << std::endl; } - std::cout << LOG("INFO") << "End Statistics for Module " << mod_num << std::endl; + + std::cout << LOG("INFO") << "End Statistics for Module " << mod.number << std::endl; csv_output.close(); return true; } @@ -227,37 +284,43 @@ bool execute_adjust_offsets(const module_config& module) { return true; } -bool execute_baseline_capture(const unsigned short& module_number) { - std::cout << LOG("INFO") << "Starting baseline capture for Module " << module_number - << std::endl; - if (!verify_api_return_value(Pixie16AcquireBaselines(module_number), "Pixie16AcquireBaselines")) +bool execute_baseline_capture(const module_config& mod) { + std::cout << LOG("INFO") << "Starting baseline capture for Module " << mod.number << std::endl; + if (!verify_api_return_value(Pixie16AcquireBaselines(mod.number), "Pixie16AcquireBaselines")) return false; - double baselines[NUMBER_OF_CHANNELS][MAX_NUM_BASELINES]; - double timestamps[MAX_NUM_BASELINES]; - for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { - std::cout << LOG("INFO") << "Acquiring baselines for Channel " << i << std::endl; - if (!verify_api_return_value(Pixie16ReadSglChanBaselines(baselines[i], timestamps, - MAX_NUM_BASELINES, module_number, - i), + std::vector> baselines; + std::vector> timestamps; + unsigned int max_num_baselines = 0; + for (unsigned int i = 0; i < mod.number_of_channels; i++) { + PixieGetMaxNumBaselines(mod.number, i, &max_num_baselines); + std::vector baseline(max_num_baselines); + std::vector timestamp(max_num_baselines); + + std::cout << LOG("INFO") << "Acquiring " << max_num_baselines << " baselines for Channel " + << i << std::endl; + if (!verify_api_return_value(Pixie16ReadSglChanBaselines(baseline.data(), timestamp.data(), + max_num_baselines, mod.number, i), "Pixie16ReadsglChanBaselines")) return false; + baselines.push_back(baseline); + timestamps.push_back(timestamp); } - std::ofstream ofstream1(generate_filename(module_number, "baselines", "csv")); + std::ofstream ofstream1(generate_filename(mod.number, "baselines", "csv")); ofstream1 << "bin,timestamp,"; - for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { - if (i != NUMBER_OF_CHANNELS - 1) + for (unsigned int i = 0; i < mod.number_of_channels; i++) { + if (i != static_cast(mod.number_of_channels - 1)) ofstream1 << "Chan" << i << ","; else ofstream1 << "Chan" << i; } ofstream1 << std::endl; - for (unsigned int i = 0; i < MAX_NUM_BASELINES; i++) { - ofstream1 << i << "," << timestamps[i] << ","; - for (unsigned int k = 0; k < NUMBER_OF_CHANNELS; k++) { - if (k != NUMBER_OF_CHANNELS - 1) + for (unsigned int i = 0; i < max_num_baselines; i++) { + ofstream1 << i << "," << timestamps[0][i] << ","; + for (unsigned int k = 0; k < mod.number_of_channels; k++) { + if (k != static_cast(mod.number_of_channels - 1)) ofstream1 << baselines[k][i] << ","; else ofstream1 << baselines[k][i]; @@ -267,78 +330,101 @@ bool execute_baseline_capture(const unsigned short& module_number) { return true; } -bool execute_list_mode_run(const configuration& cfg, const double& runtime_in_seconds) { +bool execute_list_mode_run(unsigned int run_num, const configuration& cfg, + const double& runtime_in_seconds, unsigned int synch_wait, + unsigned int in_synch) { std::cout << LOG("INFO") << "Starting list mode data run for " << runtime_in_seconds << " s." << std::endl; - std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to read SYNCH_WAIT in Module 0." - << std::endl; - unsigned int parData; - if (!verify_api_return_value(Pixie16ReadSglModPar("SYNCH_WAIT", &parData, 0), - "Pixie16ReadSglModPar - SYNC_WAIT")) - return false; - std::cout << LOG("INFO") << "SYNCH_WAIT in Module 0. = " << parData - << std::endl; - - - std::cout << LOG("INFO") << "Calling Pixie16ReadSglModPar to read IN_SYNCH in Module 0." - << std::endl; - if (!verify_api_return_value(Pixie16ReadSglModPar("IN_SYNCH", &parData, 0), - "Pixie16ReadSglModPar - IN_SYNC")) - return false; - std::cout << LOG("INFO") << "IN_SYNCH in Module 0. = " << parData - << std::endl; - - std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = 1 in Module 0." - << std::endl; - if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", 1, 0), + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = " << synch_wait + << " in Module 0." << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", synch_wait, 0), "Pixie16WriteSglModPar - SYNC_WAIT")) return false; - std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = 0 in Module 0." - << std::endl; - if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", 0, 0), + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = " << in_synch + << " in Module 0." << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", in_synch, 0), "Pixie16WriteSglModPar - IN_SYNC")) return false; - std::cout << LOG("INFO") << "Calling Pixie16StartListModeRun." << std::endl; + std::cout << LOG("INFO") << "Starting list-mode run." << std::endl; if (!verify_api_return_value(Pixie16StartListModeRun(cfg.num_modules(), LIST_MODE_RUN, NEW_RUN), "Pixie16StartListModeRun")) return false; std::vector output_streams(cfg.num_modules()); for (unsigned short i = 0; i < cfg.num_modules(); i++) { - output_streams[i] = new std::ofstream(generate_filename(i, "list-mode", "evt"), - std::ios::out | std::ios::binary); + output_streams[i] = new std::ofstream( + generate_filename(i, "list-mode-run" + std::to_string(run_num), "bin"), + std::ios::out | std::ios::binary); } - std::vector data(EXTERNAL_FIFO_LENGTH, 0); unsigned int num_fifo_words = 0; std::cout << LOG("INFO") << "Collecting data for " << runtime_in_seconds << " s." << std::endl; std::chrono::steady_clock::time_point run_start_time = std::chrono::steady_clock::now(); - while (std::chrono::duration_cast>( - std::chrono::steady_clock::now() - run_start_time) - .count() < runtime_in_seconds) { - // for (unsigned short mod_num = 0; mod_num < cfg.num_modules(); mod_num++) { - for (unsigned short mod_num = 0; mod_num < 1; mod_num++) { + double current_run_time = 0; + double check_time = 0; + bool run_status = Pixie16CheckRunStatus(cfg.modules[0].number); + + while (run_status != 0) { + current_run_time = std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count(); + + if (current_run_time >= runtime_in_seconds) { + if (synch_wait == 0) { + std::cout << LOG("INFO") << "Stopping list-mode run individually." << std::endl; + if (!verify_api_return_value(Pixie16EndRun(cfg.num_modules()), "Pixie16EndRun")) + return false; + } else { + /* + * Stop run in the Director module (module #0) - a SYNC interrupt should be generated + * to stop run in all modules simultaneously + */ + std::cout << LOG("INFO") << "Stopping list-mode run in director module." + << std::endl; + if (!verify_api_return_value(Pixie16EndRun(cfg.modules[0].number), "Pixie16EndRun")) + return false; + } + + break; + } + + if (current_run_time - check_time > 1) { + if (current_run_time < runtime_in_seconds) + std::cout << LOG("INFO") << "Remaining run time: " + << std::round(runtime_in_seconds - current_run_time) << " s" << std::endl; + check_time = current_run_time; + } + + for (unsigned short mod_num = 0; mod_num < cfg.num_modules(); mod_num++) { if (Pixie16CheckRunStatus(mod_num) == 1) { if (!verify_api_return_value( Pixie16CheckExternalFIFOStatus(&num_fifo_words, mod_num), "Pixie16CheckExternalFIFOStatus", false)) return false; - if (double(num_fifo_words) / EXTERNAL_FIFO_LENGTH > 0.2) { - std::cout << LOG("INFO") << "External FIFO has " << num_fifo_words << " words." - << std::endl; + + std::cout << LOG("INFO") << "FIFO has " << num_fifo_words << " words." << std::endl; + /* + * NOTE: The PixieSDK now uses threaded list-mode FIFO workers that live on the host machine. These + * workers perform execute in parallel. They'll read the data from each module as needed to + * ensure that the EXTERNAL_FIFO_LENGTH isn't exceeded. When calling + * `Pixie16CheckExternalFIFOStatus`, you're actually checking the status of the FIFO workers for + * that module. + * + * We've gated the reads in this example using one-second intervals, but you don't have to. + */ + if (num_fifo_words > 0) { + std::vector data(num_fifo_words, 0xDEADBEEF); if (!verify_api_return_value( Pixie16ReadDataFromExternalFIFO(data.data(), num_fifo_words, mod_num), "Pixie16ReadDataFromExternalFIFO", false)) return false; output_streams[mod_num]->write(reinterpret_cast(data.data()), num_fifo_words * sizeof(uint32_t)); - } else { - continue; } } else { std::cout << LOG("INFO") << "Module " << mod_num << " has no active run!" @@ -347,25 +433,15 @@ bool execute_list_mode_run(const configuration& cfg, const double& runtime_in_se } /* - Check the run status of the Director module (module #0) to see if the run has been stopped. - This is possible in a multi-chassis system where modules in one chassis can stop the run - in all chassis. + * Check the run status of the Director module (module #0) to see if the run has been stopped. + * This is possible in a multi-chassis system where modules in one chassis can stop the run + * in all chassis. */ - if (Pixie16CheckRunStatus(0) == 0) { - std::cout << LOG("INFO") - << "Run was stopped by the director module. Stopping data collection." - << std::endl; - break; - } - } + run_status = Pixie16CheckRunStatus(cfg.modules[0].number); - /* - Stop run in the Director module (module #0) - a SYNC interrupt should be generated - to stop run in all modules simultaneously - */ - std::cout << LOG("INFO") << "Stopping List Mode Run." << std::endl; - if (!verify_api_return_value(Pixie16EndRun(0), "Pixie16EndRun")) - return false; + //Temper the thread so that we don't slam the module with run status requests. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } std::cout << LOG("INFO") << "Checking that the run is finalized in all the modules." << std::endl; @@ -407,6 +483,7 @@ bool execute_list_mode_run(const configuration& cfg, const double& runtime_in_se if (num_fifo_words > 0) { std::cout << LOG("INFO") << "External FIFO has " << num_fifo_words << " words." << std::endl; + std::vector data(num_fifo_words, 0xDEADBEEF); if (!verify_api_return_value( Pixie16ReadDataFromExternalFIFO(data.data(), num_fifo_words, mod_num), "Pixie16ReadDataFromExternalFIFO", false)) @@ -414,112 +491,178 @@ bool execute_list_mode_run(const configuration& cfg, const double& runtime_in_se output_streams[mod_num]->write(reinterpret_cast(data.data()), num_fifo_words * sizeof(uint32_t)); } - if (!output_statistics_data(mod_num, "list-mode-stats")) { + if (!output_statistics_data(cfg.modules[mod_num], + "list-mode-stats-run" + std::to_string(run_num))) { return false; } } + for (auto& stream : output_streams) + stream->close(); + return true; } -bool execute_mca_run(const unsigned int& mod, const double& runtime_in_seconds) { +bool execute_list_mode_runs(const unsigned int num_runs, const configuration& cfg, + const double& runtime_in_seconds, unsigned int synch_wait, + unsigned int in_synch) { + for (unsigned int i = 0; i < num_runs; i++) { + std::cout << LOG("INFO") << "Starting list-mode run number " << i << std::endl; + if (!execute_list_mode_run(i, cfg, runtime_in_seconds, synch_wait, in_synch)) { + std::cout << LOG("INFO") << "List-mode data run " << i + << " failed! See log for more details." << std::endl; + return false; + } + std::cout << LOG("INFO") << "Finished list-mode run number " << i << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + return true; +} + +bool execute_mca_run(const int run_num, const module_config& mod, const double runtime_in_seconds, + unsigned int synch_wait, unsigned int in_synch) { std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write HOST_RT_PRESET to " << runtime_in_seconds << std::endl; - if (!verify_api_return_value( - Pixie16WriteSglModPar("HOST_RT_PRESET", Decimal2IEEEFloating(runtime_in_seconds), mod), - "Pixie16WriteSglModPar - HOST_RT_PRESET")) + if (!verify_api_return_value(Pixie16WriteSglModPar("HOST_RT_PRESET", + Decimal2IEEEFloating(runtime_in_seconds), + mod.number), + "Pixie16WriteSglModPar - HOST_RT_PRESET")) return false; - std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = 1 in Module 0." - << std::endl; - if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", 1, mod), + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = " << synch_wait + << " in Module 0." << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", synch_wait, mod.number), "Pixie16WriteSglModPar - SYNC_WAIT")) return false; - std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = 0 in Module 0." - << std::endl; - if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", 0, mod), + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = " << in_synch + << " in Module 0." << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", in_synch, mod.number), "Pixie16WriteSglModPar - IN_SYNC")) return false; std::cout << LOG("INFO") << "Starting MCA data run for " << runtime_in_seconds << " s." << std::endl; - if (!verify_api_return_value(Pixie16StartHistogramRun(mod, NEW_RUN), + if (!verify_api_return_value(Pixie16StartHistogramRun(mod.number, NEW_RUN), "Pixie16StartHistogramRun")) return false; - std::chrono::steady_clock::time_point run_start_time = std::chrono::steady_clock::now(); - while (std::chrono::duration_cast>( - std::chrono::steady_clock::now() - run_start_time) - .count() < runtime_in_seconds) { - //do nothing - } - std::cout << LOG("INFO") << "Stopping MCA data run after " - << std::chrono::duration_cast>( - std::chrono::steady_clock::now() - run_start_time) - .count() - << " s." << std::endl; - if (!verify_api_return_value(Pixie16EndRun(mod), "Pixie16EndRun")) - return false; + auto run_start_time = std::chrono::steady_clock::now(); + double current_run_time = 0; + double check_time = 0; + bool run_status = Pixie16CheckRunStatus(mod.number); + while (run_status != 0) { + current_run_time = std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count(); - std::string name = generate_filename(mod, "mca", "csv"); + if (current_run_time - check_time > 1) { + run_status = Pixie16CheckRunStatus(mod.number); + if (current_run_time < runtime_in_seconds) + std::cout << LOG("INFO") + << "Remaining run time: " << runtime_in_seconds - current_run_time << " s" + << std::endl; + check_time = current_run_time; + } + + if (current_run_time > runtime_in_seconds + 5) { + std::cout << LOG("ERROR") << "MCA Run failed to stop in the module!" << std::endl; + std::cout << LOG("WARN") << "Forcing end of MCA run." << std::endl; + if (!verify_api_return_value(Pixie16EndRun(mod.number), "Pixie16EndRun")) + return false; + } + } + + if (current_run_time < runtime_in_seconds) { + std::cout << LOG("ERROR") << "MCA Run exited prematurely! Check log for more details." + << std::endl; + } else { + //@todo We need to temporarily execute a manual end run until P16-440 is complete. + if (!verify_api_return_value(Pixie16EndRun(mod.number), "Pixie16EndRun")) + return false; + std::cout << LOG("INFO") << "MCA Run finished!" << std::endl; + } + + std::string name = generate_filename(mod.number, "mca-run" + std::to_string(run_num), "csv"); std::ofstream out(name); out << "bin,"; std::vector> hists; - for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { - std::vector hist(MAX_HISTOGRAM_LENGTH, 0); - Pixie16ReadHistogramFromModule(hist.data(), MAX_HISTOGRAM_LENGTH, mod, i); + unsigned int max_histogram_length = 0; + for (unsigned int i = 0; i < mod.number_of_channels; i++) { + unsigned int tmp = 0; + PixieGetHistogramLength(mod.number, i, &tmp); + std::vector hist(tmp, 0); + if (hist.size() > max_histogram_length) + max_histogram_length = hist.size(); + + Pixie16ReadHistogramFromModule(hist.data(), hist.size(), mod.number, i); hists.push_back(hist); - if (i < NUMBER_OF_CHANNELS - 1) + if (i < static_cast(mod.number_of_channels - 1)) out << "Chan" << i << ","; else out << "Chan" << i; } out << std::endl; - for (unsigned int bin = 0; bin < MAX_HISTOGRAM_LENGTH; bin++) { + for (unsigned int bin = 0; bin < max_histogram_length; bin++) { out << bin << ","; for (auto& hist : hists) { + std::string val = " "; + if (bin < hist.size()) + val = std::to_string(hist[bin]); if (&hist != &hists.back()) - out << hist[bin] << ","; + out << val << ","; else - out << hist[bin]; + out << val; } out << std::endl; } - if (!output_statistics_data(mod, "mca-stats")) { + if (!output_statistics_data(mod, "mca-stats-run" + std::to_string(run_num))) { return false; } return true; } +bool execute_mca_runs(const unsigned int num_runs, const module_config& mod, + const double runtime_in_seconds, unsigned int synch_wait, + unsigned int in_synch) { + for (unsigned int i = 0; i < num_runs; i++) { + std::cout << LOG("INFO") << "Starting MCA run number " << i << std::endl; + if (!execute_mca_run(i, mod, runtime_in_seconds, synch_wait, in_synch)) { + std::cout << LOG("INFO") << "MCA data run " << i + << " failed! See log for more details."; + return false; + } + std::cout << LOG("INFO") << "Finished MCA run number " << i << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + return true; +} + bool execute_parameter_read(args::ValueFlag& parameter, - args::ValueFlag& crate, - args::ValueFlag& module, + args::ValueFlag& crate, const unsigned int module, args::ValueFlag& channel) { if (channel) { double result; std::cout << LOG("INFO") << "Pixie16ReadSglChanPar" << " reading " << parameter.Get() << " from Crate " << crate.Get() << " Module " - << module.Get() << " Channel " << channel.Get() << "." << std::endl; - if (!verify_api_return_value(Pixie16ReadSglChanPar(parameter.Get().c_str(), &result, - module.Get(), channel.Get()), - "Pixie16ReadSglChanPar", false)) + << module << " Channel " << channel.Get() << "." << std::endl; + if (!verify_api_return_value( + Pixie16ReadSglChanPar(parameter.Get().c_str(), &result, module, channel.Get()), + "Pixie16ReadSglChanPar", false)) return false; - std::cout << LOG("INFO") << result << std::endl; + std::cout << LOG("INFO") << parameter.Get() << "=" << result << std::endl; } else { unsigned int result; std::cout << LOG("INFO") << "Pixie16ReadSglModPar reading " << parameter.Get() - << " from Crate " << crate.Get() << " Module " << module.Get() << "." - << std::endl; - if (!verify_api_return_value( - Pixie16ReadSglModPar(parameter.Get().c_str(), &result, module.Get()), - "Pixie16ReadSglModPar", false)) + << " from Crate " << crate.Get() << " Module " << module << "." << std::endl; + if (!verify_api_return_value(Pixie16ReadSglModPar(parameter.Get().c_str(), &result, module), + "Pixie16ReadSglModPar", false)) return false; - std::cout << LOG("INFO") << result << std::endl; + std::cout << LOG("INFO") << parameter.Get() << "=" << result << std::endl; } return true; } @@ -527,6 +670,8 @@ bool execute_parameter_read(args::ValueFlag& parameter, bool execute_parameter_write(args::ValueFlag& parameter, args::ValueFlag& value, args::ValueFlag& crate, const module_config& module, args::ValueFlag& channel) { + std::cout << LOG("INFO") << "Checking current value for " << parameter.Get() << std::endl; + execute_parameter_read(parameter, crate, module.number, channel); if (channel) { std::cout << LOG("INFO") << "Pixie16WriteSglChanPar setting " << parameter.Get() << " to " << value.Get() << " for Crate " << crate.Get() << " Module " << module.number @@ -545,42 +690,56 @@ bool execute_parameter_write(args::ValueFlag& parameter, return false; } + std::cout << LOG("INFO") << "Verifying written value for value for " << parameter.Get() + << std::endl; + execute_parameter_read(parameter, crate, module.number, channel); + if (!save_dsp_pars(module.dsp_par)) return false; return true; } -bool execute_trace_capture(const unsigned short& module_number) { - std::cout << LOG("INFO") << "Pixie16AcquireADCTrace acquiring traces for Module " - << module_number << "." << std::endl; - if (!verify_api_return_value(Pixie16AcquireADCTrace(module_number), "Pixie16AcquireADCTrace")) +bool execute_trace_capture(const module_config& mod) { + std::cout << LOG("INFO") << "Pixie16AcquireADCTrace acquiring traces for Module " << mod.number + << "." << std::endl; + if (!verify_api_return_value(Pixie16AcquireADCTrace(mod.number), "Pixie16AcquireADCTrace")) return false; + std::ofstream ofstream1(generate_filename(mod.number, "adc", "csv")); + ofstream1 << "bin,"; + + unsigned int max_trace_length = 0; + std::vector> traces; + for (unsigned int i = 0; i < mod.number_of_channels; i++) { + unsigned int tmp = 0; + PixieGetTraceLength(mod.number, i, &tmp); + std::vector trace(tmp, 0); + if (trace.size() > max_trace_length) + max_trace_length = trace.size(); - unsigned short trace[NUMBER_OF_CHANNELS][MAX_ADC_TRACE_LEN]; - for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { if (!verify_api_return_value( - Pixie16ReadSglChanADCTrace(trace[i], MAX_ADC_TRACE_LEN, module_number, i), + Pixie16ReadSglChanADCTrace(trace.data(), trace.size(), mod.number, i), "Pixie16AcquireADCTrace", false)) return false; - } + traces.push_back(trace); - std::ofstream ofstream1(generate_filename(module_number, "adc", "csv")); - ofstream1 << "bin,"; - for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { - if (i != NUMBER_OF_CHANNELS - 1) + if (i != static_cast(mod.number_of_channels - 1)) ofstream1 << "Chan" << i << ","; else ofstream1 << "Chan" << i; } ofstream1 << std::endl; - for (unsigned int i = 0; i < MAX_ADC_TRACE_LEN; i++) { - ofstream1 << i << ","; - for (unsigned int k = 0; k < NUMBER_OF_CHANNELS; k++) { - if (k != NUMBER_OF_CHANNELS - 1) - ofstream1 << trace[k][i] << ","; + + for (unsigned int idx = 0; idx < max_trace_length; idx++) { + ofstream1 << idx << ","; + for (auto& trace : traces) { + std::string val = " "; + if (idx < trace.size()) + val = std::to_string(trace[idx]); + if (&trace != &traces.back()) + ofstream1 << val << ","; else - ofstream1 << trace[k][i]; + ofstream1 << val; } ofstream1 << std::endl; } @@ -602,20 +761,17 @@ bool execute_blcut(args::ValueFlag& module, args::ValueFlag& module) { - if (!module) - return false; - - std::cout << LOG("INFO") << "Executing Pixie16SetDACs for Module" << module.Get() << "." +bool execute_set_dacs(const module_config& module) { + std::cout << LOG("INFO") << "Executing Pixie16SetDACs for Module" << module.number << "." << std::endl; - if (!verify_api_return_value(Pixie16SetDACs(module.Get()), "Pixie16SetDACs", false)) + if (!verify_api_return_value(Pixie16SetDACs(module.number), "Pixie16SetDACs", false)) return false; return true; } bool execute_close_module_connection(const int& numModules) { std::cout << LOG("INFO") << "Closing out connection to Modules." << std::endl; - verify_api_return_value(Pixie16ExitSystem(numModules),"Pixie16ExitSystem"); + verify_api_return_value(Pixie16ExitSystem(numModules), "Pixie16ExitSystem"); return true; } @@ -624,25 +780,41 @@ double calculate_duration_in_seconds(const std::chrono::system_clock::time_point return std::chrono::duration(end - start).count(); } -void output_module_info(const configuration& cfg) { - unsigned short rev; - unsigned int serial_number; - unsigned short adc_bits; - unsigned short adc_msps; - for (const auto& mod : cfg.modules) { - if (!verify_api_return_value( - Pixie16ReadModuleInfo(mod.number, &rev, &serial_number, &adc_bits, &adc_msps), - "Pixie16ReadModuleInfo", false)) - throw std::runtime_error("Could not get module information for Module " + - std::to_string(mod.number)); - std::cout << LOG("INFO") << "Begin module information for Module " << mod.number - << std::endl; - std::cout << LOG("INFO") << "Serial Number: " << serial_number << std::endl; - std::cout << LOG("INFO") << "Revision: " << rev << std::endl; - std::cout << LOG("INFO") << "ADC Bits: " << adc_bits << std::endl; - std::cout << LOG("INFO") << "ADC MSPS: " << adc_msps << std::endl; - std::cout << LOG("INFO") << "End module information for Module " << mod.number << std::endl; - } +void output_module_worker_info(const size_t mod_num) { + fifo_worker_config worker_config; + if (!verify_api_return_value(PixieGetWorkerConfiguration(mod_num, &worker_config), + "PixieGetWorkerConfiguration", false)) + throw std::runtime_error("Could not get worker information for Module " + + std::to_string(mod_num)); + std::cout << LOG("INFO") << "Begin List-Mode FIFO worker information for Module " << mod_num + << std::endl; + std::cout << LOG("INFO") << "Bandwidth (MB/sec): " << worker_config.bandwidth_mb_per_sec + << std::endl; + std::cout << LOG("INFO") << "Buffers : " << worker_config.buffers << std::endl; + std::cout << LOG("INFO") << "DMA Trigger Level (B): " << worker_config.dma_trigger_level_bytes + << std::endl; + std::cout << LOG("INFO") << "Hold (usec): " << worker_config.hold_usecs << std::endl; + std::cout << LOG("INFO") << "Idle wait (usec): " << worker_config.idle_wait_usecs << std::endl; + std::cout << LOG("INFO") << "Run wait (usec): " << worker_config.run_wait_usecs << std::endl; + std::cout << LOG("INFO") << "End List-Mode FIFO worker information for Module " << mod_num + << std::endl; +} + +void output_module_info(module_config& mod) { + if (!verify_api_return_value(Pixie16ReadModuleInfo(mod.number, &mod.revision, + &mod.serial_number, &mod.adc_bit_resolution, + &mod.adc_sampling_frequency, + &mod.number_of_channels), + "Pixie16ReadModuleInfo", false)) + throw std::runtime_error("Could not get module information for Module " + + std::to_string(mod.number)); + std::cout << LOG("INFO") << "Begin module information for Module " << mod.number << std::endl; + std::cout << LOG("INFO") << "Serial Number: " << mod.serial_number << std::endl; + std::cout << LOG("INFO") << "Revision: " << mod.revision << std::endl; + std::cout << LOG("INFO") << "ADC Bits: " << mod.adc_bit_resolution << std::endl; + std::cout << LOG("INFO") << "ADC MSPS: " << mod.adc_sampling_frequency << std::endl; + std::cout << LOG("INFO") << "Num Channels: " << mod.number_of_channels << std::endl; + std::cout << LOG("INFO") << "End module information for Module " << mod.number << std::endl; } @@ -681,20 +853,20 @@ int main(int argc, char** argv) { args::ValueFlag additional_cfg_flag( arguments, "cfg", "The configuration file to load.", {"additional-config"}); args::HelpFlag help_flag(arguments, "help", "Displays this message", {'h', "help"}); - args::Flag is_fast_boot(boot, "fast-boot", "Performs a partial boot of the system.", - {'f', "fast-boot"}); args::Flag is_offline(arguments, "Offline Mode", "Tells the API to use Offline mode when running.", {'o', "offline"}); args::ValueFlag boot_pattern_flag(arguments, "boot_pattern", "The boot pattern used for booting.", {'b', "boot_pattern"}, "0x7F"); - args::ValueFlag run_time( - list_mode, "time", "The amount of time that a list mode run will take in seconds.", - {'t', "run-time"}, 10.); + args::ValueFlag run_time(list_mode, "time", + "The amount of time that a data run will take in seconds.", + {'t', "run-time"}, 10.); args::ValueFlag parameter( arguments, "parameter", "The parameter we want to read from the system.", {'n', "name"}); - args::ValueFlag channel(arguments, "channel", "The channel to operate on.", - {"chan"}); + args::ValueFlag channel( + arguments, "channel", + "The channel to operate on. If set to the maximum number of channels in the module, then reads/writes execute for all channels.", + {"chan"}); args::ValueFlag crate(arguments, "crate", "The crate", {"crate"}, 0); args::ValueFlag copy_mask( copy, "copy_mask", "An integer representing the set of parameters to copy", {"copy-mask"}); @@ -705,15 +877,23 @@ int main(int argc, char** argv) { args::ValueFlag dest_module(copy, "dest_module", "The module that we'll copy to.", {"dest-mod"}); args::ValueFlag module(arguments, "module", "The module to operate on.", {"mod"}); + args::ValueFlag num_runs( + arguments, "num_runs", "The number of runs to execute when taking list-mode or MCA data.", + {"num-runs"}, static_cast(1)); args::ValueFlag parameter_value( write, "parameter_value", "The value of the parameter we want to write.", {'v', "value"}); + args::ValueFlag synch_wait( + list_mode, "synch_wait", + "SynchWait = 0 to start/stop runs independently. (default)\nSynchWait = 1 to start/stop runs synchronously.", + {"synch-wait"}, static_cast(0)); + args::ValueFlag in_synch( + list_mode, "in_synch", + "InSynch = 0 to reset clocks prior to starting a run. (default)\nInSynch = 1 to take no clock action.", + {"in-synch"}, static_cast(0)); adjust_offsets.Add(conf_flag); adjust_offsets.Add(boot_pattern_flag); - adjust_offsets.Add(module); - baseline.Add(is_fast_boot); baseline.Add(boot_pattern_flag); - baseline.Add(module); blcut.Add(module); blcut.Add(channel); boot.Add(conf_flag); @@ -722,8 +902,13 @@ int main(int argc, char** argv) { copy.Add(module); copy.Add(channel); dacs.Add(module); + list_mode.Add(num_runs); mca.Add(module); mca.Add(boot_pattern_flag); + mca.Add(synch_wait); + mca.Add(in_synch); + mca.Add(num_runs); + mca.Add(run_time); read.Add(conf_flag); read.Add(crate); read.Add(module); @@ -731,7 +916,6 @@ int main(int argc, char** argv) { read.Add(parameter); tau_finder.Add(module); trace.Add(conf_flag); - trace.Add(module); trace.Add(boot_pattern_flag); write.Add(conf_flag); write.Add(parameter); @@ -779,7 +963,16 @@ int main(int argc, char** argv) { << std::endl; try { - output_module_info(cfg); + for (auto& mod : cfg.modules) { + output_module_info(mod); + if (mod.has_worker_cfg) { + if (!verify_api_return_value( + PixieSetWorkerConfiguration(mod.number, &mod.worker_config), + "PixieSetWorkerConfiguration", false)) + return EXIT_FAILURE; + } + output_module_worker_info(mod.number); + } } catch (std::runtime_error& error) { std::cout << LOG("ERROR") << error.what() << std::endl; return EXIT_FAILURE; @@ -791,22 +984,82 @@ int main(int argc, char** argv) { } unsigned int boot_pattern = stoul(args::get(boot_pattern_flag), nullptr, 0); - if (is_fast_boot || additional_cfg_flag) + if (additional_cfg_flag) boot_pattern = 0x70; - for (const auto& mod : cfg.modules) { + bool crate_boot = false; + std::string par_file; + for (auto& mod : cfg.modules) { + if (mod.fw.version != 0) { + std::cout << LOG("INFO") << "Calling PixieRegisterFirmware for Module " << mod.number + << ": sys" << std::endl; + int rc = PixieRegisterFirmware(mod.fw.version, mod.fw.revision, mod.fw.adc_msps, + mod.fw.adc_bits, "sys", mod.com_fpga_config.c_str(), + mod.number); + if (!verify_api_return_value(rc, "PixieRegisterFirmware", false)) + return EXIT_FAILURE; + std::cout << LOG("INFO") << "Calling PixieRegisterFirmware for Module " << mod.number + << ": fippi" << std::endl; + rc = PixieRegisterFirmware(mod.fw.version, mod.fw.revision, mod.fw.adc_msps, + mod.fw.adc_bits, "fippi", mod.sp_fpga_config.c_str(), + mod.number); + if (!verify_api_return_value(rc, "PixieRegisterFirmware", false)) + return EXIT_FAILURE; + std::cout << LOG("INFO") << "Calling PixieRegisterFirmware for Module " << mod.number + << ": dsp" << std::endl; + rc = PixieRegisterFirmware(mod.fw.version, mod.fw.revision, mod.fw.adc_msps, + mod.fw.adc_bits, "dsp", mod.dsp_code.c_str(), mod.number); + if (!verify_api_return_value(rc, "PixieRegisterFirmware", false)) + return EXIT_FAILURE; + std::cout << LOG("INFO") << "Calling PixieRegisterFirmware for Module " << mod.number + << ": var" << std::endl; + rc = PixieRegisterFirmware(mod.fw.version, mod.fw.revision, mod.fw.adc_msps, + mod.fw.adc_bits, "var", mod.dsp_var.c_str(), mod.number); + if (!verify_api_return_value(rc, "PixieRegisterFirmware", false)) + return EXIT_FAILURE; + par_file = mod.dsp_par; + crate_boot = true; + } else { + start = std::chrono::system_clock::now(); + std::cout << LOG("INFO") << "Calling Pixie16BootModule for Module " << mod.number + << " with boot pattern: " << std::showbase << std::hex << boot_pattern + << std::dec << std::endl; + + if (!verify_api_return_value( + Pixie16BootModule(mod.com_fpga_config.c_str(), mod.sp_fpga_config.c_str(), + nullptr, mod.dsp_code.c_str(), mod.dsp_par.c_str(), + mod.dsp_var.c_str(), mod.number, boot_pattern), + "Pixie16BootModule", "Finished booting!")) + return EXIT_FAILURE; + std::cout << LOG("INFO") << "Finished Pixie16BootModule for Module " << mod.number + << " in " + << calculate_duration_in_seconds(start, std::chrono::system_clock::now()) + << " s." << std::endl; + } + } + + if (crate_boot) { start = std::chrono::system_clock::now(); - std::cout << LOG("INFO") << "Calling Pixie16BootModule for Module " << mod.number - << " with boot pattern: " << std::showbase << std::hex << boot_pattern << std::dec + std::cout << LOG("INFO") << "Calling PixieBootCrate with settings: " << par_file << std::endl; - if (!verify_api_return_value( - Pixie16BootModule(mod.com_fpga_config.c_str(), mod.sp_fpga_config.c_str(), nullptr, - mod.dsp_code.c_str(), mod.dsp_par.c_str(), mod.dsp_var.c_str(), - mod.number, boot_pattern), - "Pixie16BootModule", "Finished booting!")) + PIXIE_BOOT_MODE boot_mode; + switch (boot_pattern) { + case 0x00: + boot_mode = PIXIE_BOOT_PROBE; + break; + case 0x70: + boot_mode = PIXIE_BOOT_SETTINGS_LOAD; + break; + case 0x7F: + default: + boot_mode = PIXIE_BOOT_RESET_LOAD; + } + + int rc = PixieBootCrate(par_file.c_str(), boot_mode); + if (!verify_api_return_value(rc, "PixieBootCrate", false)) return EXIT_FAILURE; - std::cout << LOG("INFO") << "Finished Pixie16BootModule for Module " << mod.number << " in " + std::cout << LOG("INFO") << "Finished PixieBootCrate in " << calculate_duration_in_seconds(start, std::chrono::system_clock::now()) << " s." << std::endl; } @@ -831,18 +1084,18 @@ int main(int argc, char** argv) { "and the destination mask to execute!" << std::endl; } - std::vector dest_mask; - for(size_t mod = 0; mod < cfg.num_modules(); mod++) { - for(size_t chan = 0; chan < NUMBER_OF_CHANNELS; chan++) { + std::vector dest_masks; + for (size_t mod = 0; mod < cfg.num_modules(); mod++) { + for (size_t chan = 0; chan < cfg.modules[mod].number_of_channels; chan++) { if (mod == dest_module.Get() && chan == dest_channel.Get()) - dest_mask.push_back(1); + dest_masks.push_back(1); else - dest_mask.push_back(0); + dest_masks.push_back(0); } } - if (!verify_api_return_value( - Pixie16CopyDSPParameters(copy_mask.Get(), module.Get(), channel.Get(), dest_mask.data()), - "Pixie16CopyDSPParameters", true)) { + if (!verify_api_return_value(Pixie16CopyDSPParameters(copy_mask.Get(), module.Get(), + channel.Get(), dest_masks.data()), + "Pixie16CopyDSPParameters", true)) { return EXIT_FAILURE; } } @@ -852,7 +1105,8 @@ int main(int argc, char** argv) { std::cout << LOG("ERROR") << "Pixie16TauFinder requires the module flag to execute!" << std::endl; } - std::vector taus(NUMBER_OF_CHANNELS); + + std::vector taus(cfg.modules[module.Get()].number_of_channels); if (!verify_api_return_value(Pixie16TauFinder(module.Get(), taus.data()), "Pixie16TauFinder", true)) { return EXIT_FAILURE; @@ -863,28 +1117,48 @@ int main(int argc, char** argv) { } if (read) { - if (!execute_parameter_read(parameter, crate, module, channel)) - return EXIT_FAILURE; + auto mod = cfg.modules[module.Get()]; + if (channel.Get() >= mod.number_of_channels) { + for (unsigned int ch = 0; ch < mod.number_of_channels; ch++) { + channel.ParseValue(std::vector(1, std::to_string(ch))); + if (!execute_parameter_read(parameter, crate, module.Get(), channel)) + return EXIT_FAILURE; + } + } else { + if (!execute_parameter_read(parameter, crate, module.Get(), channel)) + return EXIT_FAILURE; + } } if (write) { - if (!execute_parameter_write(parameter, parameter_value, crate, cfg.modules[module.Get()], - channel)) - return EXIT_FAILURE; + auto mod = cfg.modules[module.Get()]; + if (channel.Get() >= mod.number_of_channels) { + for (unsigned int ch = 0; ch < mod.number_of_channels; ch++) { + channel.ParseValue(std::vector(1, std::to_string(ch))); + if (!execute_parameter_write(parameter, parameter_value, crate, mod, channel)) + return EXIT_FAILURE; + } + } else { + if (!execute_parameter_write(parameter, parameter_value, crate, mod, channel)) + return EXIT_FAILURE; + } } if (adjust_offsets) { - if (!execute_adjust_offsets(cfg.modules[module.Get()])) - return EXIT_FAILURE; + for (auto& mod : cfg.modules) + if (!execute_adjust_offsets(mod)) + return EXIT_FAILURE; } if (trace) { - if (!execute_trace_capture(module.Get())) - return EXIT_FAILURE; + for (auto& mod : cfg.modules) + if (!execute_trace_capture(mod)) + return EXIT_FAILURE; } if (list_mode) { - if (!execute_list_mode_run(cfg, run_time.Get())) + if (!execute_list_mode_runs(num_runs.Get(), cfg, run_time.Get(), synch_wait.Get(), + in_synch.Get())) return EXIT_FAILURE; } @@ -894,13 +1168,23 @@ int main(int argc, char** argv) { } if (baseline) { - if (!execute_baseline_capture(module.Get())) - return EXIT_FAILURE; + for (auto& mod : cfg.modules) + if (!execute_baseline_capture(mod)) + return EXIT_FAILURE; } if (mca) { - if (!execute_mca_run(module.Get(), run_time.Get())) - return EXIT_FAILURE; + if (module.Get() >= cfg.num_modules()) { + for (auto& mod : cfg.modules) { + if (!execute_mca_runs(num_runs.Get(), mod, run_time.Get(), synch_wait.Get(), + in_synch.Get())) + return EXIT_FAILURE; + } + } else { + if (!execute_mca_runs(num_runs.Get(), cfg.modules[module.Get()], run_time.Get(), + synch_wait.Get(), in_synch.Get())) + return EXIT_FAILURE; + } } if (blcut) { @@ -909,8 +1193,9 @@ int main(int argc, char** argv) { } if (dacs) { - if (!execute_set_dacs(module)) - return EXIT_FAILURE; + for (auto& mod : cfg.modules) + if (!execute_set_dacs(mod)) + return EXIT_FAILURE; } execute_close_module_connection(cfg.num_modules()); diff --git a/example_3.2.cpp b/example_3.2.cpp new file mode 100644 index 0000000..e7cd358 --- /dev/null +++ b/example_3.2.cpp @@ -0,0 +1,917 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * Copyright 2021 XIA LLC, All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file example_pixie16api.cpp + * @brief Demonstrates how to use the Pixie16Api functions to communicate with Pixie-16 modules. + * + * We demonstrate both the PixieSDK implementation using `Pixie16Api.so` and the Legacy C + * implementation using `Pixie16App.so`. The only difference between using one library over the + * other is in the header definitions. + * + * The `Pixie16Api.so` includes all the goodness that comes with using the C++ implementation + * just with a convenient C wrapper. Users don't have as much control over the nitty-gritty details + * of the PixieSDK. We've intentionally limited this to prevent this backward compatible API from + * growing out of hand. We **really** recommend that you link your code directly with `PixieSDK.a`. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +struct LOG { + explicit LOG(const std::string& type) { + type_ = type; + + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::time_t currentTime = std::chrono::system_clock::to_time_t(now); + std::chrono::milliseconds now2 = + std::chrono::duration_cast(now.time_since_epoch()); + char timeBuffer[80]; + std::strftime(timeBuffer, 80, "%FT%T", gmtime(¤tTime)); + + std::stringstream tmp; + tmp << timeBuffer << "." << std::setfill('0') << std::setw(3) << now2.count() % 1000 << "Z"; + + datetime_ = tmp.str(); + } + + friend std::ostream& operator<<(std::ostream& os, const LOG& log) { + os << log.datetime_ << " - " << log.type_ << " - "; + return os; + } + + std::string type_; + std::string datetime_; +}; + +struct module_config { + unsigned short slot; + unsigned short number; + std::string com_fpga_config; + std::string sp_fpga_config; + std::string dsp_code; + std::string dsp_par; + std::string dsp_var; +}; + +typedef std::vector module_configs; + +struct configuration { + module_configs modules; + std::vector slot_def; + unsigned short num_modules() const { + return static_cast(modules.size()); + } +}; + +std::string generate_filename(const unsigned int& module_number, const std::string& type, + const std::string& ext) { +#ifndef LEGACY_EXAMPLE + static const std::string file_prefix = "pixie16api-module"; +#else + static const std::string file_prefix = "pixie16app-module"; +#endif + return file_prefix + std::to_string(module_number) + "-" + type + "." + ext; +} + +void verify_json_module(const nlohmann::json& mod) { + if (!mod.contains("slot")) { + throw std::invalid_argument("Missing slot definition in configuration element."); + } + + if (!mod.contains("dsp")) { + throw std::invalid_argument("Missing dsp object in configuration element."); + } + + if (!mod["dsp"].contains("ldr") || !mod["dsp"].contains("var") || !mod["dsp"].contains("par")) { + throw std::invalid_argument( + "Missing dsp object in configuration element: ldr, dsp, or par."); + } + + if (!mod.contains("fpga")) { + throw std::invalid_argument("Missing fpga object in configuration element."); + } + + if (!mod["fpga"].contains("fippi") || !mod["fpga"].contains("sys")) { + throw std::invalid_argument("Missing fpga firmware definition (fippi or sys)."); + } +} + +void read_config(const std::string& config_file_name, configuration& cfg) { + std::ifstream input(config_file_name, std::ios::in); + if (input.fail()) { + throw std::ios_base::failure("open: " + config_file_name + ": " + std::strerror(errno)); + } + + nlohmann::json jf = nlohmann::json::parse(input); + input.close(); + + if (jf.empty() || jf.size() > SYS_MAX_NUM_MODULES) { + throw std::invalid_argument("invalid number of modules"); + } + + cfg.slot_def.clear(); + for (const auto& module : jf) { + verify_json_module(module); + + cfg.slot_def.push_back(module["slot"]); + + module_config mod_cfg; + mod_cfg.slot = module["slot"]; + mod_cfg.number = static_cast(cfg.slot_def.size() - 1); + mod_cfg.com_fpga_config = module["fpga"]["sys"]; + mod_cfg.sp_fpga_config = module["fpga"]["fippi"]; + mod_cfg.dsp_code = module["dsp"]["ldr"]; + mod_cfg.dsp_par = module["dsp"]["par"]; + mod_cfg.dsp_var = module["dsp"]["var"]; + cfg.modules.push_back(mod_cfg); + } +} + +bool verify_api_return_value(const int& val, const std::string& func_name, + const bool& print_success = true) { + if (val < 0) { + std::cout << LOG("ERROR") << func_name << " failed with Error Code " << val << std::endl; + return false; + } + if (print_success) + std::cout << LOG("INFO") << func_name << " finished successfully." << std::endl; + return true; +} + +bool output_statistics_data(const unsigned short& mod_num, const std::string& type) { +#ifndef LEGACY_EXAMPLE + std::vector stats(Pixie16GetStatisticsSize(), 0); +#else + std::vector stats(N_DSP_PAR - DSP_IO_BORDER, 0); +#endif + if (!verify_api_return_value(Pixie16ReadStatisticsFromModule(stats.data(), mod_num), + "Pixie16ReadStatisticsFromModule", false)) + return false; + + std::ofstream bin_output(generate_filename(mod_num, type, "bin"), + std::ios::binary | std::ios::out); + bin_output.write(reinterpret_cast(stats.data()), sizeof(unsigned int) * stats.size()); + bin_output.close(); + + std::ofstream csv_output(generate_filename(mod_num, type, "csv"), std::ios::out); + csv_output << "channel,real_time,live_time,input_count_rate,output_count_rate" << std::endl; + + auto real_time = Pixie16ComputeRealTime(stats.data(), mod_num); + + std::cout << LOG("INFO") << "Begin Statistics for Module " << mod_num << std::endl; + std::cout << LOG("INFO") << "Real Time: " << real_time << std::endl; + for (unsigned int chan = 0; chan < NUMBER_OF_CHANNELS; chan++) { + auto live_time = Pixie16ComputeLiveTime(stats.data(), mod_num, chan); + auto icr = Pixie16ComputeInputCountRate(stats.data(), mod_num, chan); + auto ocr = Pixie16ComputeOutputCountRate(stats.data(), mod_num, chan); + + std::cout << LOG("INFO") << "Channel " << chan << " LiveTime: " << live_time << std::endl; + std::cout << LOG("INFO") << "Channel " << chan << " Input Count Rate: " << icr << std::endl; + std::cout << LOG("INFO") << "Channel " << chan << " Output Count Rate: " << ocr + << std::endl; + + csv_output << chan << "," << real_time << "," << live_time << "," << icr << "," << ocr + << std::endl; + } + std::cout << LOG("INFO") << "End Statistics for Module " << mod_num << std::endl; + csv_output.close(); + return true; +} + + +bool save_dsp_pars(const std::string& filename) { + std::cout << LOG("INFO") << "Saving DSP Parameters to " << filename << "." << std::endl; + if (!verify_api_return_value(Pixie16SaveDSPParametersToFile(filename.c_str()), + "Pixie16SaveDSPParametersToFile")) + return false; + return true; +} + +bool execute_adjust_offsets(const module_config& module) { + std::cout << LOG("INFO") << "Adjusting baseline offset for Module " << module.number << "." + << std::endl; + if (!verify_api_return_value(Pixie16AdjustOffsets(module.number), + "Pixie16AdjustOffsets for Module " + + std::to_string(module.number))) + return false; + if (!save_dsp_pars(module.dsp_par)) + return false; + return true; +} + +bool execute_baseline_capture(const unsigned short& module_number) { + std::cout << LOG("INFO") << "Starting baseline capture for Module " << module_number + << std::endl; + if (!verify_api_return_value(Pixie16AcquireBaselines(module_number), "Pixie16AcquireBaselines")) + return false; + + double baselines[NUMBER_OF_CHANNELS][MAX_NUM_BASELINES]; + double timestamps[MAX_NUM_BASELINES]; + for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { + std::cout << LOG("INFO") << "Acquiring baselines for Channel " << i << std::endl; + if (!verify_api_return_value(Pixie16ReadSglChanBaselines(baselines[i], timestamps, + MAX_NUM_BASELINES, module_number, + i), + "Pixie16ReadsglChanBaselines")) + return false; + } + + std::ofstream ofstream1(generate_filename(module_number, "baselines", "csv")); + ofstream1 << "bin,timestamp,"; + for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { + if (i != NUMBER_OF_CHANNELS - 1) + ofstream1 << "Chan" << i << ","; + else + ofstream1 << "Chan" << i; + } + ofstream1 << std::endl; + + for (unsigned int i = 0; i < MAX_NUM_BASELINES; i++) { + ofstream1 << i << "," << timestamps[i] << ","; + for (unsigned int k = 0; k < NUMBER_OF_CHANNELS; k++) { + if (k != NUMBER_OF_CHANNELS - 1) + ofstream1 << baselines[k][i] << ","; + else + ofstream1 << baselines[k][i]; + } + ofstream1 << std::endl; + } + return true; +} + +bool execute_list_mode_run(const configuration& cfg, const double& runtime_in_seconds) { + std::cout << LOG("INFO") << "Starting list mode data run for " << runtime_in_seconds << " s." + << std::endl; + + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to read SYNCH_WAIT in Module 0." + << std::endl; + unsigned int parData; + if (!verify_api_return_value(Pixie16ReadSglModPar("SYNCH_WAIT", &parData, 0), + "Pixie16ReadSglModPar - SYNC_WAIT")) + return false; + std::cout << LOG("INFO") << "SYNCH_WAIT in Module 0. = " << parData + << std::endl; + + + std::cout << LOG("INFO") << "Calling Pixie16ReadSglModPar to read IN_SYNCH in Module 0." + << std::endl; + if (!verify_api_return_value(Pixie16ReadSglModPar("IN_SYNCH", &parData, 0), + "Pixie16ReadSglModPar - IN_SYNC")) + return false; + std::cout << LOG("INFO") << "IN_SYNCH in Module 0. = " << parData + << std::endl; + + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = 1 in Module 0." + << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", 1, 0), + "Pixie16WriteSglModPar - SYNC_WAIT")) + return false; + + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = 0 in Module 0." + << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", 0, 0), + "Pixie16WriteSglModPar - IN_SYNC")) + return false; + + std::cout << LOG("INFO") << "Calling Pixie16StartListModeRun." << std::endl; + if (!verify_api_return_value(Pixie16StartListModeRun(cfg.num_modules(), LIST_MODE_RUN, NEW_RUN), + "Pixie16StartListModeRun")) + return false; + + std::vector output_streams(cfg.num_modules()); + for (unsigned short i = 0; i < cfg.num_modules(); i++) { + output_streams[i] = new std::ofstream(generate_filename(i, "list-mode", "evt"), + std::ios::out | std::ios::binary); + } + + std::vector data(EXTERNAL_FIFO_LENGTH, 0); + unsigned int num_fifo_words = 0; + + std::cout << LOG("INFO") << "Collecting data for " << runtime_in_seconds << " s." << std::endl; + std::chrono::steady_clock::time_point run_start_time = std::chrono::steady_clock::now(); + while (std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count() < runtime_in_seconds) { + // for (unsigned short mod_num = 0; mod_num < cfg.num_modules(); mod_num++) { + for (unsigned short mod_num = 0; mod_num < 1; mod_num++) { + if (Pixie16CheckRunStatus(mod_num) == 1) { + if (!verify_api_return_value( + Pixie16CheckExternalFIFOStatus(&num_fifo_words, mod_num), + "Pixie16CheckExternalFIFOStatus", false)) + return false; + + if (double(num_fifo_words) / EXTERNAL_FIFO_LENGTH > 0.2) { + std::cout << LOG("INFO") << "External FIFO has " << num_fifo_words << " words." + << std::endl; + if (!verify_api_return_value( + Pixie16ReadDataFromExternalFIFO(data.data(), num_fifo_words, mod_num), + "Pixie16ReadDataFromExternalFIFO", false)) + return false; + output_streams[mod_num]->write(reinterpret_cast(data.data()), + num_fifo_words * sizeof(uint32_t)); + } else { + continue; + } + } else { + std::cout << LOG("INFO") << "Module " << mod_num << " has no active run!" + << std::endl; + } + } + + /* + Check the run status of the Director module (module #0) to see if the run has been stopped. + This is possible in a multi-chassis system where modules in one chassis can stop the run + in all chassis. + */ + if (Pixie16CheckRunStatus(0) == 0) { + std::cout << LOG("INFO") + << "Run was stopped by the director module. Stopping data collection." + << std::endl; + break; + } + } + + /* + Stop run in the Director module (module #0) - a SYNC interrupt should be generated + to stop run in all modules simultaneously + */ + std::cout << LOG("INFO") << "Stopping List Mode Run." << std::endl; + if (!verify_api_return_value(Pixie16EndRun(0), "Pixie16EndRun")) + return false; + + std::cout << LOG("INFO") << "Checking that the run is finalized in all the modules." + << std::endl; + bool all_modules_finished = false; + const unsigned int max_finalize_attempts = 50; + for (unsigned int counter = 0; counter < max_finalize_attempts; counter++) { + for (unsigned short k = 0; k < cfg.num_modules(); k++) { + if (Pixie16CheckRunStatus(k) == 1) { + all_modules_finished = false; + } else { + all_modules_finished = true; + } + } + if (all_modules_finished) { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (!all_modules_finished) { + std::cout << LOG("ERROR") << "All modules did not stop their runs properly!" << std::endl; + return false; + } + + std::cout << LOG("INFO") << "List-mode run finished in " + << std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count() + << " s" << std::endl; + + std::cout << LOG("INFO") + << "Reading the final words from the External FIFO and the run statistics." + << std::endl; + for (unsigned short mod_num = 0; mod_num < cfg.num_modules(); mod_num++) { + if (!verify_api_return_value(Pixie16CheckExternalFIFOStatus(&num_fifo_words, mod_num), + "Pixie16CheckExternalFIFOStatus", false)) + return false; + + if (num_fifo_words > 0) { + std::cout << LOG("INFO") << "External FIFO has " << num_fifo_words << " words." + << std::endl; + if (!verify_api_return_value( + Pixie16ReadDataFromExternalFIFO(data.data(), num_fifo_words, mod_num), + "Pixie16ReadDataFromExternalFIFO", false)) + return false; + output_streams[mod_num]->write(reinterpret_cast(data.data()), + num_fifo_words * sizeof(uint32_t)); + } + if (!output_statistics_data(mod_num, "list-mode-stats")) { + return false; + } + } + + return true; +} + +bool execute_mca_run(const unsigned int& mod, const double& runtime_in_seconds) { + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write HOST_RT_PRESET to " + << runtime_in_seconds << std::endl; + if (!verify_api_return_value( + Pixie16WriteSglModPar("HOST_RT_PRESET", Decimal2IEEEFloating(runtime_in_seconds), mod), + "Pixie16WriteSglModPar - HOST_RT_PRESET")) + return false; + + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write SYNCH_WAIT = 1 in Module 0." + << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("SYNCH_WAIT", 1, mod), + "Pixie16WriteSglModPar - SYNC_WAIT")) + return false; + + std::cout << LOG("INFO") << "Calling Pixie16WriteSglModPar to write IN_SYNCH = 0 in Module 0." + << std::endl; + if (!verify_api_return_value(Pixie16WriteSglModPar("IN_SYNCH", 0, mod), + "Pixie16WriteSglModPar - IN_SYNC")) + return false; + + std::cout << LOG("INFO") << "Starting MCA data run for " << runtime_in_seconds << " s." + << std::endl; + if (!verify_api_return_value(Pixie16StartHistogramRun(mod, NEW_RUN), + "Pixie16StartHistogramRun")) + return false; + + std::chrono::steady_clock::time_point run_start_time = std::chrono::steady_clock::now(); + while (std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count() < runtime_in_seconds) { + //do nothing + } + std::cout << LOG("INFO") << "Stopping MCA data run after " + << std::chrono::duration_cast>( + std::chrono::steady_clock::now() - run_start_time) + .count() + << " s." << std::endl; + if (!verify_api_return_value(Pixie16EndRun(mod), "Pixie16EndRun")) + return false; + + std::string name = generate_filename(mod, "mca", "csv"); + std::ofstream out(name); + out << "bin,"; + + std::vector> hists; + for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { + std::vector hist(MAX_HISTOGRAM_LENGTH, 0); + Pixie16ReadHistogramFromModule(hist.data(), MAX_HISTOGRAM_LENGTH, mod, i); + hists.push_back(hist); + if (i < NUMBER_OF_CHANNELS - 1) + out << "Chan" << i << ","; + else + out << "Chan" << i; + } + out << std::endl; + + for (unsigned int bin = 0; bin < MAX_HISTOGRAM_LENGTH; bin++) { + out << bin << ","; + for (auto& hist : hists) { + if (&hist != &hists.back()) + out << hist[bin] << ","; + else + out << hist[bin]; + } + out << std::endl; + } + + if (!output_statistics_data(mod, "mca-stats")) { + return false; + } + + return true; +} + +bool execute_parameter_read(args::ValueFlag& parameter, + args::ValueFlag& crate, + args::ValueFlag& module, + args::ValueFlag& channel) { + if (channel) { + double result; + std::cout << LOG("INFO") << "Pixie16ReadSglChanPar" + << " reading " << parameter.Get() << " from Crate " << crate.Get() << " Module " + << module.Get() << " Channel " << channel.Get() << "." << std::endl; + if (!verify_api_return_value(Pixie16ReadSglChanPar(parameter.Get().c_str(), &result, + module.Get(), channel.Get()), + "Pixie16ReadSglChanPar", false)) + return false; + std::cout << LOG("INFO") << result << std::endl; + } else { + unsigned int result; + std::cout << LOG("INFO") << "Pixie16ReadSglModPar reading " << parameter.Get() + << " from Crate " << crate.Get() << " Module " << module.Get() << "." + << std::endl; + if (!verify_api_return_value( + Pixie16ReadSglModPar(parameter.Get().c_str(), &result, module.Get()), + "Pixie16ReadSglModPar", false)) + return false; + std::cout << LOG("INFO") << result << std::endl; + } + return true; +} + +bool execute_parameter_write(args::ValueFlag& parameter, + args::ValueFlag& value, args::ValueFlag& crate, + const module_config& module, args::ValueFlag& channel) { + if (channel) { + std::cout << LOG("INFO") << "Pixie16WriteSglChanPar setting " << parameter.Get() << " to " + << value.Get() << " for Crate " << crate.Get() << " Module " << module.number + << " Channel " << channel.Get() << "." << std::endl; + if (!verify_api_return_value(Pixie16WriteSglChanPar(parameter.Get().c_str(), value.Get(), + module.number, channel.Get()), + "Pixie16WriteSglChanPar")) + return false; + } else { + std::cout << LOG("INFO") << "Pixie16WriteSglModPar" + << " setting " << parameter.Get() << " to " << value.Get() << " for Crate " + << crate.Get() << " Module " << module.number << "." << std::endl; + if (!verify_api_return_value( + Pixie16WriteSglModPar(parameter.Get().c_str(), value, module.number), + "Pixie16WriteSglModPar")) + return false; + } + + if (!save_dsp_pars(module.dsp_par)) + return false; + return true; +} + +bool execute_trace_capture(const unsigned short& module_number) { + std::cout << LOG("INFO") << "Pixie16AcquireADCTrace acquiring traces for Module " + << module_number << "." << std::endl; + if (!verify_api_return_value(Pixie16AcquireADCTrace(module_number), "Pixie16AcquireADCTrace")) + return false; + + + unsigned short trace[NUMBER_OF_CHANNELS][MAX_ADC_TRACE_LEN]; + for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { + if (!verify_api_return_value( + Pixie16ReadSglChanADCTrace(trace[i], MAX_ADC_TRACE_LEN, module_number, i), + "Pixie16AcquireADCTrace", false)) + return false; + } + + std::ofstream ofstream1(generate_filename(module_number, "adc", "csv")); + ofstream1 << "bin,"; + for (unsigned int i = 0; i < NUMBER_OF_CHANNELS; i++) { + if (i != NUMBER_OF_CHANNELS - 1) + ofstream1 << "Chan" << i << ","; + else + ofstream1 << "Chan" << i; + } + ofstream1 << std::endl; + for (unsigned int i = 0; i < MAX_ADC_TRACE_LEN; i++) { + ofstream1 << i << ","; + for (unsigned int k = 0; k < NUMBER_OF_CHANNELS; k++) { + if (k != NUMBER_OF_CHANNELS - 1) + ofstream1 << trace[k][i] << ","; + else + ofstream1 << trace[k][i]; + } + ofstream1 << std::endl; + } + return true; +} + +bool execute_blcut(args::ValueFlag& module, args::ValueFlag& channel) { + if (!module) + return false; + + std::cout << LOG("INFO") << "Executing Pixie16BLcutFinder for Module" << module.Get() << "." + << std::endl; + unsigned int blcut = 0; + if (!verify_api_return_value(Pixie16BLcutFinder(module.Get(), channel.Get(), &blcut), + "Pixie16BLcutFinder", false)) + return false; + std::cout << LOG("INFO") << "BLCut for Module " << module.Get() << " Channel " << channel.Get() + << " is " << blcut << std::endl; + return true; +} + +bool execute_set_dacs(args::ValueFlag& module) { + if (!module) + return false; + + std::cout << LOG("INFO") << "Executing Pixie16SetDACs for Module" << module.Get() << "." + << std::endl; + if (!verify_api_return_value(Pixie16SetDACs(module.Get()), "Pixie16SetDACs", false)) + return false; + return true; +} + +bool execute_close_module_connection(const int& numModules) { + std::cout << LOG("INFO") << "Closing out connection to Modules." << std::endl; + verify_api_return_value(Pixie16ExitSystem(numModules),"Pixie16ExitSystem"); + return true; +} + +double calculate_duration_in_seconds(const std::chrono::system_clock::time_point& start, + const std::chrono::system_clock::time_point& end) { + return std::chrono::duration(end - start).count(); +} + +void output_module_info(const configuration& cfg) { + unsigned short rev; + unsigned int serial_number; + unsigned short adc_bits; + unsigned short adc_msps; + for (const auto& mod : cfg.modules) { + if (!verify_api_return_value( + Pixie16ReadModuleInfo(mod.number, &rev, &serial_number, &adc_bits, &adc_msps), + "Pixie16ReadModuleInfo", false)) + throw std::runtime_error("Could not get module information for Module " + + std::to_string(mod.number)); + std::cout << LOG("INFO") << "Begin module information for Module " << mod.number + << std::endl; + std::cout << LOG("INFO") << "Serial Number: " << serial_number << std::endl; + std::cout << LOG("INFO") << "Revision: " << rev << std::endl; + std::cout << LOG("INFO") << "ADC Bits: " << adc_bits << std::endl; + std::cout << LOG("INFO") << "ADC MSPS: " << adc_msps << std::endl; + std::cout << LOG("INFO") << "End module information for Module " << mod.number << std::endl; + } +} + + +int main(int argc, char** argv) { + auto start = std::chrono::system_clock::now(); + args::ArgumentParser parser( + "Sample code that interfaces with a Pixie system through the User API."); + parser.LongSeparator("="); + + args::Group commands(parser, "commands"); + args::Command boot(commands, "boot", "Boots the crate of modules."); + args::Command copy(commands, "copy", "Copies DSP parameters from source to destination."); + args::Command export_settings( + commands, "export-settings", + "Boots the system and dumps the settings to the file defined in the config."); + args::Command histogram(commands, "histogram", "Save histograms from the module."); + args::Command init(commands, "init", "Initializes the system without going any farther."); + args::Command list_mode(commands, "list-mode", "Starts a list mode data run"); + args::Command read(commands, "read", "Read a parameter from the module."); + args::Command write(commands, "write", "Write a parameter to the module."); + args::Command trace(commands, "trace", "Captures traces from the modules."); + args::Command adjust_offsets(commands, "adjust_offsets", + "Adjusts the DC offsets for all modules in the config file."); + args::Command baseline(commands, "baseline", "Acquire and print baselines from the module"); + args::Command mca(commands, "mca", "Starts an MCA data run."); + args::Command blcut(commands, "blcut", + "Starts a control task to find the BLCut for a channel."); + args::Command dacs(commands, "dacs", "Starts a control task to set the module's DACs"); + args::Command tau_finder(commands, "tau_finder", + "Executes the Tau Finder control task and returns the values."); + + args::Group arguments(parser, "arguments", args::Group::Validators::AtLeastOne, + args::Options::Global); + args::ValueFlag conf_flag(arguments, "cfg", "The configuration file to load.", + {'c', "config"}, args::Options::Required); + args::ValueFlag additional_cfg_flag( + arguments, "cfg", "The configuration file to load.", {"additional-config"}); + args::HelpFlag help_flag(arguments, "help", "Displays this message", {'h', "help"}); + args::Flag is_fast_boot(boot, "fast-boot", "Performs a partial boot of the system.", + {'f', "fast-boot"}); + args::Flag is_offline(arguments, "Offline Mode", + "Tells the API to use Offline mode when running.", {'o', "offline"}); + args::ValueFlag boot_pattern_flag(arguments, "boot_pattern", + "The boot pattern used for booting.", + {'b', "boot_pattern"}, "0x7F"); + args::ValueFlag run_time( + list_mode, "time", "The amount of time that a list mode run will take in seconds.", + {'t', "run-time"}, 10.); + args::ValueFlag parameter( + arguments, "parameter", "The parameter we want to read from the system.", {'n', "name"}); + args::ValueFlag channel(arguments, "channel", "The channel to operate on.", + {"chan"}); + args::ValueFlag crate(arguments, "crate", "The crate", {"crate"}, 0); + args::ValueFlag copy_mask( + copy, "copy_mask", "An integer representing the set of parameters to copy", {"copy-mask"}); + args::ValueFlag dest_mask( + copy, "dest_mask", "An integer representing the destination channels", {"dest-mask"}); + args::ValueFlag dest_channel(copy, "dest_channel", + "The channel that we'll copy to", {"dest-chan"}); + args::ValueFlag dest_module(copy, "dest_module", "The module that we'll copy to.", + {"dest-mod"}); + args::ValueFlag module(arguments, "module", "The module to operate on.", {"mod"}); + args::ValueFlag parameter_value( + write, "parameter_value", "The value of the parameter we want to write.", {'v', "value"}); + + adjust_offsets.Add(conf_flag); + adjust_offsets.Add(boot_pattern_flag); + adjust_offsets.Add(module); + baseline.Add(is_fast_boot); + baseline.Add(boot_pattern_flag); + baseline.Add(module); + blcut.Add(module); + blcut.Add(channel); + boot.Add(conf_flag); + boot.Add(boot_pattern_flag); + copy.Add(boot_pattern_flag); + copy.Add(module); + copy.Add(channel); + dacs.Add(module); + mca.Add(module); + mca.Add(boot_pattern_flag); + read.Add(conf_flag); + read.Add(crate); + read.Add(module); + read.Add(channel); + read.Add(parameter); + tau_finder.Add(module); + trace.Add(conf_flag); + trace.Add(module); + trace.Add(boot_pattern_flag); + write.Add(conf_flag); + write.Add(parameter); + write.Add(crate); + write.Add(module); + write.Add(channel); + + try { + parser.ParseCLI(argc, argv); + } catch (args::Help& help) { + std::cout << LOG("INFO") << help.what() << std::endl; + std::cout << parser; + return EXIT_SUCCESS; + } catch (args::Error& e) { + std::cout << LOG("ERROR") << e.what() << std::endl; + std::cout << parser; + return EXIT_FAILURE; + } + + configuration cfg; + try { + read_config(conf_flag.Get(), cfg); + } catch (std::exception& e) { + std::cout << LOG("ERROR") << e.what() << std::endl; + return EXIT_FAILURE; + } + + std::cout << LOG("INFO") << "Finished reading config in " + << calculate_duration_in_seconds(start, std::chrono::system_clock::now()) << " s." + << std::endl; + + int offline_mode = 0; + if (is_offline) + offline_mode = 1; + + start = std::chrono::system_clock::now(); + std::cout << LOG("INFO") << "Calling Pixie16InitSystem." << std::endl; + if (!verify_api_return_value( + Pixie16InitSystem(cfg.num_modules(), cfg.slot_def.data(), offline_mode), + "Pixie16InitSystem", false)) + return EXIT_FAILURE; + + std::cout << LOG("INFO") << "Finished Pixie16InitSystem in " + << calculate_duration_in_seconds(start, std::chrono::system_clock::now()) << " s." + << std::endl; + + try { + output_module_info(cfg); + } catch (std::runtime_error& error) { + std::cout << LOG("ERROR") << error.what() << std::endl; + return EXIT_FAILURE; + } + + if (init) { + execute_close_module_connection(cfg.num_modules()); + return EXIT_SUCCESS; + } + + unsigned int boot_pattern = stoul(args::get(boot_pattern_flag), nullptr, 0); + if (is_fast_boot || additional_cfg_flag) + boot_pattern = 0x70; + + for (const auto& mod : cfg.modules) { + start = std::chrono::system_clock::now(); + std::cout << LOG("INFO") << "Calling Pixie16BootModule for Module " << mod.number + << " with boot pattern: " << std::showbase << std::hex << boot_pattern << std::dec + << std::endl; + + if (!verify_api_return_value( + Pixie16BootModule(mod.com_fpga_config.c_str(), mod.sp_fpga_config.c_str(), nullptr, + mod.dsp_code.c_str(), mod.dsp_par.c_str(), mod.dsp_var.c_str(), + mod.number, boot_pattern), + "Pixie16BootModule", "Finished booting!")) + return EXIT_FAILURE; + std::cout << LOG("INFO") << "Finished Pixie16BootModule for Module " << mod.number << " in " + << calculate_duration_in_seconds(start, std::chrono::system_clock::now()) << " s." + << std::endl; + } + + if (boot) { + execute_close_module_connection(cfg.num_modules()); + return EXIT_SUCCESS; + } + + if (additional_cfg_flag) { + if (!verify_api_return_value( + Pixie16LoadDSPParametersFromFile(additional_cfg_flag.Get().c_str()), + "Pixie16LoadDSPParametersFromFile", true)) + return EXIT_FAILURE; + } + + if (copy) { + if (!module || !channel || !copy_mask || !dest_channel || !dest_module) { + std::cout + << LOG("ERROR") + << "Pixie16CopyDSPParameters requires the source/destination module and channel " + "and the destination mask to execute!" + << std::endl; + } + std::vector dest_mask; + for(size_t mod = 0; mod < cfg.num_modules(); mod++) { + for(size_t chan = 0; chan < NUMBER_OF_CHANNELS; chan++) { + if (mod == dest_module.Get() && chan == dest_channel.Get()) + dest_mask.push_back(1); + else + dest_mask.push_back(0); + } + } + if (!verify_api_return_value( + Pixie16CopyDSPParameters(copy_mask.Get(), module.Get(), channel.Get(), dest_mask.data()), + "Pixie16CopyDSPParameters", true)) { + return EXIT_FAILURE; + } + } + + if (tau_finder) { + if (!module) { + std::cout << LOG("ERROR") << "Pixie16TauFinder requires the module flag to execute!" + << std::endl; + } + std::vector taus(NUMBER_OF_CHANNELS); + if (!verify_api_return_value(Pixie16TauFinder(module.Get(), taus.data()), + "Pixie16TauFinder", true)) { + return EXIT_FAILURE; + } + for (unsigned int i = 0; i < taus.size(); i++) { + std::cout << "Channel " << i << ": " << taus.at(i) << std::endl; + } + } + + if (read) { + if (!execute_parameter_read(parameter, crate, module, channel)) + return EXIT_FAILURE; + } + + if (write) { + if (!execute_parameter_write(parameter, parameter_value, crate, cfg.modules[module.Get()], + channel)) + return EXIT_FAILURE; + } + + if (adjust_offsets) { + if (!execute_adjust_offsets(cfg.modules[module.Get()])) + return EXIT_FAILURE; + } + + if (trace) { + if (!execute_trace_capture(module.Get())) + return EXIT_FAILURE; + } + + if (list_mode) { + if (!execute_list_mode_run(cfg, run_time.Get())) + return EXIT_FAILURE; + } + + if (export_settings) { + if (!save_dsp_pars(cfg.modules.front().dsp_par)) + return EXIT_FAILURE; + } + + if (baseline) { + if (!execute_baseline_capture(module.Get())) + return EXIT_FAILURE; + } + + if (mca) { + if (!execute_mca_run(module.Get(), run_time.Get())) + return EXIT_FAILURE; + } + + if (blcut) { + if (!execute_blcut(module, channel)) + return EXIT_FAILURE; + } + + if (dacs) { + if (!execute_set_dacs(module)) + return EXIT_FAILURE; + } + + execute_close_module_connection(cfg.num_modules()); + return EXIT_SUCCESS; +} diff --git a/pixieDAQ.cpp b/pixieDAQ.cpp index 76b47ca..bc7dd85 100644 --- a/pixieDAQ.cpp +++ b/pixieDAQ.cpp @@ -5,21 +5,30 @@ #include #include #include +#include +#include #include "pixieDAQ.h" #include "Pixie16Class.h" + +Pixie16 * pixie; MainWindow::MainWindow(const TGWindow *p,UInt_t w,UInt_t h) { + + openPixie(); + /// Create a main frame fMain = new TGMainFrame(p,w,h); + ///fMain->SetWMPosition(500, 500); //does not work /// Create canvas widget fEcanvas = new TRootEmbeddedCanvas("Ecanvas",fMain,800,400); fMain->AddFrame(fEcanvas, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); /// Create a horizontal frame widget with buttons TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,200,40); + TGTextButton *draw = new TGTextButton(hframe,"&Draw"); - draw->Connect("Clicked()","MainWindow",this,"DoDraw()"); + draw->Connect("Clicked()","MainWindow",this,"getADCTrace()"); hframe->AddFrame(draw, new TGLayoutHints(kLHintsCenterX, 5,5,3,4)); TGTextButton *exit = new TGTextButton(hframe,"&Exit"); exit->Connect("Clicked()", "MainWindow", this, "GoodBye()"); @@ -28,7 +37,7 @@ MainWindow::MainWindow(const TGWindow *p,UInt_t w,UInt_t h) { fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX,2,2,2,2)); /// Set a name to the main frame - fMain->SetWindowName("Simple Example"); + fMain->SetWindowName("Pixie16 DAQ"); /// Map all subwindows of main frame fMain->MapSubwindows(); @@ -56,11 +65,41 @@ MainWindow::~MainWindow() { delete fMain; } -void MainWindow::DoDraw() { +void MainWindow::openPixie(){ + + printf("Removing Pixie16Msg.log \n"); + remove( "Pixie16Msg.log"); + + pixie = new Pixie16(); + if ( pixie->GetStatus() < 0 ) { + printf("Exiting program... \n"); + GoodBye(); + } + +} + +void MainWindow::getADCTrace() { /// Draws function graphics in randomly chosen interval - TF1 *f1 = new TF1("f1","sin(x)/x",0,gRandom->Rndm()*10); - f1->SetLineWidth(3); - f1->Draw(); + ///TF1 *f1 = new TF1("f1","sin(x)/x",0,gRandom->Rndm()*10); + ///f1->SetLineWidth(3); + ///f1->Draw(); + + printf("--------- get ADCTrace \n"); + + int ch = 6; + pixie->CaptureADCTrace(0, ch); + + unsigned short * haha = pixie->GetADCTrace(); + double dt = pixie->GetChannelSetting("XDT", 0, ch); + + TGraph * gTrace = new TGraph(); + + for( int i = 0 ; i < pixie->GetADCTraceLength(); i++){ + gTrace->SetPoint(i, i*dt, haha[i]); + } + gTrace->GetXaxis()->SetTitle("time [us]"); + gTrace->Draw("AP"); + TCanvas *fCanvas = fEcanvas->GetCanvas(); fCanvas->cd(); fCanvas->Update(); @@ -69,15 +108,21 @@ void MainWindow::DoDraw() { void MainWindow::GoodBye(){ + + pixie->CloseDigitizers(); + printf("----- bye bye ---- \n"); + gApplication->Terminate(0); + } int main(int argc, char **argv) { printf(" Welcome to pixie16 DQ \n"); + TApplication theApp("App",&argc,argv); - new MainWindow(gClient->GetRoot(),200,200); + new MainWindow(gClient->GetRoot(),800,600); theApp.Run(); return 0; } diff --git a/pixieDAQ.h b/pixieDAQ.h index d11b85c..69c7718 100644 --- a/pixieDAQ.h +++ b/pixieDAQ.h @@ -4,20 +4,23 @@ class TGWindow; class TGMainFrame; class TRootEmbeddedCanvas; -class Pixie16; +//class Pixie16; class MainWindow { RQ_OBJECT("MainWindow") private: TGMainFrame *fMain; TRootEmbeddedCanvas *fEcanvas; - - Pixie16 * pixie; - + + public: MainWindow(const TGWindow *p, UInt_t w, UInt_t h); virtual ~MainWindow(); - void GoodBye(); - void DoDraw(); + void openPixie(); + + void getADCTrace(); + + void GoodBye(); + }; diff --git a/test.cpp b/test.cpp index d505350..2acaf96 100644 --- a/test.cpp +++ b/test.cpp @@ -79,8 +79,10 @@ int main(int argc, char *argv[]){ TH1F * hch = new TH1F("hch", "channel", 16, 0, 16); TH1F * hE = new TH1F("hE", "energy", 400, 0, 30000); TGraph * gTrace = new TGraph(); - gTrace->GetXaxis()->SetTitle("time [ch = 4 ns]"); - + + int ch2ns = pixie->GetCh2ns(0); + gTrace->GetXaxis()->SetTitle("time [ns]"); + //pixie->SetDigitizerPresetRunTime(100000, 0); //pixie->SetDigitizerSynchWait(0, 0); // not simultaneously @@ -111,33 +113,34 @@ int main(int argc, char *argv[]){ //pixie->SetChannelEnergyRiseTime(2, 0, ch); - pixie->SetChannelTriggerThreshold(300, 0, ch); + //pixie->SetChannelTriggerThreshold(300, 0, ch); //pixie->SetChannelEnergyTau(50, 0, ch); //pixie->SetChannelOnOff(true, 0, ch); //pixie->SetChannelPositivePolarity(true, 0, ch); //pixie->SetChannelTraceOnOff(true, 0, ch); - pixie->SetChannelBaseLinePrecent(90, 0, ch); - //pixie->SetChannelVOffset(0.0, 0, ch); + //pixie->SetChannelBaseLinePrecent(10, 0, ch); + //pixie->SetChannelVOffset(-0.5, 0, ch); //pixie->SetChannelTraceLenght(10, 0, ch); //pixie->SetChannelTraceDelay(2, 0, ch); - pixie->SetChannelGain(1, 0, ch); - pixie->SaveSettings("test_ryan.set"); + //pixie->SetChannelGain(1, 0, ch); + //pixie->SaveSettings("test_ryan.set"); pixie->PrintChannelAllSettings(0, ch); pixie->PrintChannelsMainSettings(0); - /* + pixie->CaptureADCTrace(0, ch); unsigned short * haha = pixie->GetADCTrace(); - double dt = GetChannelSetting("XDT", 0, ch); + double dt = pixie->GetChannelSetting("XDT", 0, ch); for( int i = 0 ; i < pixie->GetADCTraceLength(); i++){ gTrace->SetPoint(i, i*dt, haha[i]); } gTrace->GetXaxis()->SetTitle("time [us]"); canvas->cd(3); gTrace->Draw("APL"); - */ + + //pixie->CaptureBaseLine(0, ch); //double * baseline = pixie->GetBasline(); @@ -146,10 +149,10 @@ int main(int argc, char *argv[]){ // gTrace->SetPoint(i, baselineTime[i]*1000, baseline[i]); // //printf("%5d | %f, %f \n", i, baselineTime[i]*1000, baseline[i]); //} - //canvas->cd(3); gTrace->Draw("APL"); + //canvas->cd(2); gTrace->Draw("APL"); - + /* printf("start run for %f sec\n", time); uint32_t StartTime = get_time(), CurrentTime = get_time(); @@ -175,9 +178,9 @@ int main(int argc, char *argv[]){ if( data->eventID %10 == 0 ){ if( data->trace_length > 0 ) { for( int i = 0 ; i < data->trace_length; i++){ - gTrace->SetPoint(i, i, data->trace[i]); + gTrace->SetPoint(i, i*ch2ns, data->trace[i]); } - gTrace->GetYaxis()->SetRangeUser(0, 5000); + //gTrace->GetYaxis()->SetRangeUser(0, 5000); canvas->cd(3); gTrace->Draw("APL"); } } diff --git a/test_ryan.set b/test_ryan.set index 95a66b1..e855dda 100644 --- a/test_ryan.set +++ b/test_ryan.set @@ -27,7 +27,7 @@ 10, 10, 10, - 90, + 10, 10, 10, 10, @@ -423,7 +423,7 @@ 32768, 32768, 32768, - 32768, + 21845, 32768, 32768, 32768, @@ -970,7 +970,7 @@ "dsp": { "adc_bits": 16, "adc_msps": 250, - "file": "Pixie16DSP_revfgeneral_12b250m_r41847.ldr", + "file": "Pixie16DSP_revfgeneral_16b250m_r35921.ldr", "rev": 15, "tag": "15-250-16", "version": "n/a" @@ -984,7 +984,7 @@ "fippi": { "adc_bits": 16, "adc_msps": 250, - "file": "fippixie16_revfgeneral_12b250m_r42081.bin", + "file": "fippixie16_revfgeneral_16b250m_r36563.bin", "rev": 15, "tag": "15-250-16", "version": "n/a" @@ -1005,7 +1005,7 @@ "var": { "adc_bits": 16, "adc_msps": 250, - "file": "Pixie16DSP_revfgeneral_12b250m_r41847.var", + "file": "Pixie16DSP_revfgeneral_16b250m_r35921.var", "rev": 15, "tag": "15-250-16", "version": "n/a" @@ -1016,7 +1016,7 @@ "ChanNum": 0, "CoincPattern": 0, "CoincWait": 0, - "ControlTask": 6, + "ControlTask": 0, "CrateID": 0, "FIFOLength": 8188, "FastFilterRange": 0,