//------------------------------------------------------------------------------ // DAQ application task -- // (C) Devis Contarato 2009, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "task_DAQ_Main_Main.cpp" // [Author] "Devis Contarato" // [Version] "0.5" // [Modified by] "Devis Contarato" // [Last revision] "18 May 2009" // [Language] "C++" // [Compiler] "Visual C++ 8.x 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "DAQ application task" // [Key documentation] // "Visual C++ Reference Help" // {Trace} //______________________________________________________________________________ // Standard components #include #include // Application components #include "global.h" #include "cool.h" #include "task_DAQ_Main.h" // Define some standard color #define kc_Desk cool::Gui->kc_blue_Dark #define kc_desk_Label cool::Gui->kc_White #define kc_Btn cool::Gui->kc_Blue #define kc_btn_Label cool::Gui->kc_White //______________________________________________________________________________ task_DAQ_Main::task_DAQ_Main() { // Standard constructor dbg_Print("task_DAQ_Main::task_DAQ_Main: constructor called", DBG_LVL_ZERO); // Initialize the detector description task_Det = new task_DAQ_Detector(); data_Setup(); // Set up the communication comm_Setup(); // Initialize the GUI task_GUI = new task_DAQ_GUI(this); } //______________________________________________________________________________ task_DAQ_Main::~task_DAQ_Main() { // Standard destructor dbg_Print("task_DAQ_Main::~task_DAQ_Main: destructor called", DBG_LVL_ZERO); // Delete data structures data_Delete(); // Removes the GUI delete task_GUI; // Delete the detector object delete task_Det; } //______________________________________________________________________________ UInt_t task_DAQ_Main::run() { // Debug dbg_Print("task_DAQ_Main::run: run called", DBG_LVL_MAKE); // Returns all ok return 0; } //______________________________________________________________________________ void task_DAQ_Main::static_Evn(const int arg) { // Try the call to a static function dbg_Print("task_DAQ_Main::static_Evn: it works!", DBG_LVL_FLOW); } //****************************************************************************** //* * //* GUI Callback target functions * //* * //****************************************************************************** //______________________________________________________________________________ void task_DAQ_Main::btn_run_Evn(const int arg) { // Play button events handler dbg_Print("task_DAQ_Main::btn_run_Evn: run called", DBG_LVL_FLOW); // Acquire if( task_GUI->btn_Acq[0]->btn_Status() == true && endFlag ) data_Acquire(); } //______________________________________________________________________________ void task_DAQ_Main::btn_quit_Evn(const int arg) { // Quit button events handler dbg_Print("task_DAQ_Main::btn_quit_Evn: quit called", DBG_LVL_FLOW); // Exits by self-quitting the class cool::Gui->Quit(); } //______________________________________________________________________________ void task_DAQ_Main::btn_FPGA_Evn(const int arg) { // Set FPGA button event handler dbg_Print("task_DAQ_Main::btn_FPGA_evn: button has been pressed!", DBG_LVL_FLOW); set_FPGA(); } //______________________________________________________________________________ void task_DAQ_Main::btn_Comm_Evn(const int arg) { // Set Comm button event handler dbg_Print("task_DAQ_Main::btn_Comm_evn: button has been pressed!", DBG_LVL_FLOW); cool::Comm->Clear(); } //______________________________________________________________________________ void task_DAQ_Main::btn_TEAM_Evn(const int arg) { // GRETINA DEFAULT SETUP dbg_Print("task_DAQ_Main::btn_TEAM_evn: button has been pressed!", DBG_LVL_FLOW); team_Setup(); } //______________________________________________________________________________ void task_DAQ_Main::btn_reg_Evn(const int arg) { // Write if (arg == task_GUI->btn_Reg[0]->obj_Id()) { // Info std::cout << "Writing to Gretina!\n"; // Set up a pivot buffer UShort_t buff[16]; Int_t buff_Len = 16; // Fill the buffer with the numeric values for (UInt_t i = 0; i < buff_Len; i++) { buff[i] = (UShort_t)(task_GUI->num_Reg[i]->num_Val()); std::cout << task_GUI->num_Reg[i]->num_Val() << " "; } std::cout << "\n"; // Write cool::Comm->raw_Write(buff, &buff_Len); } // Read if (arg == task_GUI->btn_Reg[1]->obj_Id()) { // Info std::cout << "Reading from Gretina!\n"; // Issue the write command: // Set up buffers UShort_t wr_buff[16]; UShort_t rd_buff[256]; Int_t wr_buff_Len = 16; Int_t rd_buff_Len = 256; // Clean input buffer for (UInt_t i = 0; i < rd_buff_Len; i++) rd_buff[i] = 0; // Fill the write buffer with the numeric values std::cout << "Sending: "; for (UInt_t i = 0; i < wr_buff_Len; i++) { wr_buff[i] = (UShort_t)(task_GUI->num_Reg[i]->num_Val()); std::cout << task_GUI->num_Reg[i]->num_Val() << " "; } std::cout << "\n"; // Send the write command to the module cool::Comm->raw_Write(wr_buff, &wr_buff_Len); // Read back the data from the USB cool::Comm->raw_Read(rd_buff, &rd_buff_Len); // Show what found std::cout << "Reading: \n"; if (rd_buff_Len > 0) { for (UInt_t i = 0; i < rd_buff_Len; i++) { std::cout << "Word #" << i << ": 0x " << std::hex << rd_buff[i] << "\n"; } //std::cout << "\n"; } else { std::cout << "No answer!\n"; } } } //______________________________________________________________________________ void task_DAQ_Main::set_FPGA() { // Set FPGA settings. This function is called at the beginning of each // acquisition run. It can be called also by pressing the button "Set FPGA" // Set trigger mode (software, hardware) trigger_mode = cool::Reg->acq_Mode( task_GUI->cmb_DAQ[0]->cbox_Val() ); if( trigger_mode ){ std::cout << "Hardware trigger: "; }else{ std::cout << "Software trigger\n"; } // Set trigger source trigger_source = cool::Reg->acq_trg_Mode( task_GUI->cmb_DAQ[1]->cbox_Val() ); if( trigger_mode ){ if( trigger_source ){ std::cout << "external\n"; }else{ std::cout << "internal\n"; } } // Set internal trigger frequency trigger_period = (unsigned int)(10000/task_GUI->num_DAQ[0]->num_Val()); cool::Reg->acq_trg_Period( trigger_period ); if( trigger_mode==1 && trigger_source==0 ){ std::cout << "Internal trigger frequency " << task_GUI->num_DAQ[0]->num_Val() << ", period " << trigger_period << "\n"; } // Set chip driver driver_number = cool::Reg->acq_drv_Sel(task_GUI->cmb_DAQ[2]->cbox_Val() ); std::cout << "Chip driver " << driver_number << "\n"; // Set driver delay driver_delay = cool::Reg->acq_drv_Delay( 256*(UInt_t)task_GUI->num_DAQ[1]->num_Val() ); std::cout << "Driver delay " << driver_delay << "\n"; // Set number of frames frames_number = cool::Reg->acq_frm_Count( (UInt_t)task_GUI->num_DAQ[2]->num_Val() ); std::cout << "Number of frames " << frames_number << "\n"; // Set data source data_source = cool::Reg->acq_data_Mode( task_GUI->cmb_DAQ[3]->cbox_Val() ); std::cout << "acq_data_Mode: " << task_GUI->cmb_DAQ[3]->cbox_Val() << "\n"; // EXTREMELY IMPORTANT!!!! // Re-set data structures depending on chip driver selection and number of frames required if( task_GUI->cmb_Acq[0]->cbox_Val() != 2 ) data_Reset(); // Re-set corresponding number of data points switch( driver_number ){ case 2: std::cout << "LDRD2 chip selected\n"; cool::Reg->acq_dp_Count(task_Det->detector[0]->chip(0)->dp_Count()); break; case 3: std::cout << "SOI2 analog chip selected\n"; cool::Reg->acq_dp_Count(task_Det->detector[1]->chip(0)->dp_Count()); break; case 4: std::cout << "SOI2 digital chip selected\n"; cool::Reg->acq_dp_Count(task_Det->detector[2]->chip(0)->dp_Count()); break; case 5: std::cout << "SOI chip analog & digital selected\n"; std::cout << "WARNING!!! Detector geometry not yet implemented!!\n"; break; case 6: std::cout << "TEAM chip (1 output) selected\n"; cool::Reg->acq_dp_Count(task_Det->detector[3]->chip(0)->dp_Count()); chip_TEAM_Set(); break; case 7: std::cout << "TEAM chip (4 outputs) selected\n"; driver_number = cool::Reg->acq_drv_Sel(6); // Set correct driver, ugly but working cool::Reg->acq_dp_Count(task_Det->detector[4]->chip(0)->dp_Count()); chip_TEAM_Set(); break; case 8: std::cout << "TEAM chip (full readout) selected\n"; driver_number = cool::Reg->acq_drv_Sel(128); cool::Reg->acq_dp_Count(task_Det->detector[5]->chip(0)->dp_Count()); team_Setup(); break; default: break; } // Set the clock //cool::Reg->adc_clk_Div(4); // Clock divider, = 3.12 Mhz // Sets the acquisition mode and driver //cool::Reg->acq_drv_Sel(db_Raw->frame_Fit()->HrdID()); // TEAM driver // Sets data pipeline //cool::Reg->acq_data_Mode(4); // TEAM data source; //cool::Reg->acq_chn_Enable(15); // 4 channel acquisition // Sets data count for the packet builder //cool::Reg->acq_frm_Count(db_Raw->frame_Count()); // Frame data count //cool::Reg->acq_dp_Count(db_Raw->frame_Fit()->chip(0)->dp_Count()); // Total data count (per channel! ////////////////// // ADC SETTINGS // ////////////////// // reset counter of active ADC channels iadc = 0; int chn_Mask = 0; // Set ADC input channels for(int i=0; i<5; i++){ if( task_GUI->chk_Adc[i]->chk_Status() == true ){ std::cout << "ADC " << i+1 << " "; chn_Mask = chn_Mask + (int)pow((double)2, i); // count the number of channels which are active iadc++; } } std::cout << "selected\n"; // if the button is checked, activate the channel cool::Reg->acq_chn_Enable(chn_Mask); std::cout << "Channel mask " << chn_Mask << "\n"; // Warn if no ADC channel has been selected if( iadc == 0 ) std::cout << "No ADC channel selected!\n"; // set ADC Clock Divider adc_divider = cool::Reg->adc_clk_Div( (UInt_t)task_GUI->cmb_DAQ[4]->cbox_Val() ); std::cout << "Clock divider " << adc_divider << "\n"; // set ADC averages adc_averages = cool::Reg->adc_Avgs( (UInt_t)task_GUI->num_DAQ[3]->num_Val() ); std::cout << "Number of averages " << adc_averages << "\n"; } //______________________________________________________________________________ void task_DAQ_Main::chip_TEAM_Set() { // TEAM chip specific settings unsigned int chip_settings, chip_type, pre_delay, lvds_clk, en_diag, se_kill, adapter_board; chip_type = task_GUI->cmb_TEAM[0]->cbox_Val(); pre_delay = (UInt_t)task_GUI->num_TEAM[0]->num_Val() << 1; if( task_GUI->chk_TEAM[0]->chk_Status() == true ) lvds_clk = 0; // active low else lvds_clk = 16; // 10000 if( task_GUI->chk_TEAM[1]->chk_Status() == true ) en_diag = 0; // active low else en_diag = 32; // 100000 if( task_GUI->chk_TEAM[2]->chk_Status() == true ) se_kill = 64; // 1000000 else se_kill = 0; adapter_board = task_GUI->cmb_TEAM[1]->cbox_Val() << 15; chip_settings = chip_type | pre_delay | lvds_clk | en_diag | se_kill | adapter_board; // Write parameters into register cool::Reg->chp_Pars( chip_settings ); std::cout << "TEAM1K settings: " << chip_settings << std::endl; std::cout << "TEAM1K version: "; if ( chip_type == 0 ){ std::cout << "AMS" << std::endl; }else{ std::cout << "ELT" << std::endl; std::cout << "Pre-burner_delay: " << (pre_delay >> 1) << std::endl; if( se_kill == 0 ) std::cout << "Slew-rate enhancer active" << std::endl; else std::cout << "Slew-rate enhancer inactive" << std::endl; } if( adapter_board == 0 ){ std::cout << "Using LBNL adapter" << std::endl; }else{ std::cout << "Using PD adapter" << std::endl; if( lvds_clk == 0 ) std::cout << "LVDS clock operation" << std::endl; } } //______________________________________________________________________________ void task_DAQ_Main::team_Setup() { // Preset the data dbg_Print("task_Demo::team_Set: setting DAQ", DBG_LVL_FLOW); // Set up a pivot buffer Int_t buff_Count = 22; Int_t buff_Len = 16; UShort_t wr_Buff[22][16] = { // Sets DataNConfig to config mode {5, 0, 0, 0x8802, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets clock {5, 0, 0, 0x87c2, 0x0000, 0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x87c2, 0x0000, 0x0003, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets register DAC values {5, 0, 0, 0x8405, 0x11E4, 0x1AB8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8406, 0x0000, 0x177C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8407, 0x1AB8, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets digitizer to send clocks to the sensor and update the DAC values. {5, 0, 0, 0x8002, 0x000A, 0x8031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8402, 0x0012, 0x8002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8402, 0x0012, 0xA002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8402, 0x0012, 0x8002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Selects real data from digitizers {5, 0, 0, 0x8004, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x8404, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets image size (64 columns per output and 1024 rows, the full sector) {5, 0, 0, 0x800c, 0x0140, 0x0400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x840c, 0x0140, 0x0400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets APS clock speed {5, 0, 0, 0x800d, 0x0000, 0x0010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x800d, 0x0000, 0x0018, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x800d, 0x0000, 0x0013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x840d, 0x0000, 0x0003, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets delays from qwrap and C0 {5, 0, 0, 0x800e, 0x0000, 0x0340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0x840e, 0x0000, 0x0340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets image size on V4 (here it is 1024 * 1024) {5, 0, 0, 0x8803, 0x0400, 0x0400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sets DataNConfig {5, 0, 0, 0x8802, 0x0000, 0x0045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; // Sends the buffer for (UInt_t i = 0; i < buff_Count; i++) cool::Comm->raw_Write(wr_Buff[i], &buff_Len); // TEAM mode set! cool::Out->Print("TEAM mode set\n", LWHITE); } //****************************************************************************** //* * //* Data & Detector initialization and destruction * //* * //****************************************************************************** //______________________________________________________________________________ void task_DAQ_Main::data_Setup() { // DEFAULT: LDRD2 detector, this will change depending on driver selection burst_Raw = new data_Burst(task_Det->detector[0], 1); burst_Image = new data_Burst(task_Det->detector[0], 1); burst_Pedestal = new data_Burst(task_Det->detector[0], 1); burst_Pedestal2 = new data_Burst(task_Det->detector[0], 1); burst_Noise = new data_Burst(task_Det->detector[0], 1); burst_Mask = new data_Burst(task_Det->detector[0], 1); common_Mode.push_back(0); common_ModeNoise.push_back(0); // Initialize pedestal available flag and statistics frames pedFlag = 0; burst_Pedestal->frame(0)->dp_all_Set(0); burst_Pedestal2->frame(0)->dp_all_Set(0); burst_Noise->frame(0)->dp_all_Set(0); burst_Mask->frame(0)->dp_all_Set(0); // Variables for plot rescaling frm_Count = burst_Raw->frame_Count(); col_Count = burst_Raw->frame(0)->layer(0)->dp_col_Count(); row_Count = frm_Count * burst_Raw->frame(0)->layer(0)->dp_row_Count(); dp_Count = burst_Raw->frame(0)->layer(0)->dp_Count(); } //______________________________________________________________________________ void task_DAQ_Main::data_Delete() { // Delete the data dbg_Print("task_DAQ_Main::data_Delete: releasing data objects", DBG_LVL_FLOW); // Data delete burst_Raw; delete burst_Image; delete burst_Pedestal; delete burst_Pedestal2; delete burst_Noise; delete burst_Mask; } //****************************************************************************** //* * //* USB Communication setup * //* * //****************************************************************************** //______________________________________________________________________________ void task_DAQ_Main::comm_Setup() { // Comm setup dbg_Print("task_DAQ_Main::comm_Setup: setting up communication", DBG_LVL_FLOW); // Open USB communication cool::Comm->Open(); if (!cool::Comm->isOpen()) { std::cout << "You need to open the communication before!\n"; return; } // Set the ADC registers (default values, to be overridden by user selected ones std::cout << "Setting the ADCs...\n"; cool::Reg->adc_clk_Chn(0); // Reference ADC clock cool::Reg->adc_clk_Div(1); // Clock divider cool::Reg->adc_Avgs(0); // No averages // Set the data trigger registers (default values) std::cout << "Setting the data trigger...\n"; cool::Reg->data_trg_Mode(0); // External triggering, i.e. no data trigger cool::Reg->data_trg_Count(burst_Raw->dp_Count()); // Number of data points cool::Reg->data_trg_Delay(0); // Trigger delay cool::Reg->data_trg_Slope(0); // Positive slope cool::Reg->data_trg_Chn(0); // Channel 0 cool::Reg->data_trg_Thr(9000); // Trigger threshold // Set the acquisition mode (default values, to be overridden by user selected ones) std::cout << "Setting the acquisition mode...\n"; cool::Reg->acq_Mode(0); // Software triggered cool::Reg->acq_chn_Enable(15); // Enables 4 channels cool::Reg->acq_drv_Sel(2); // Set the driver cool::Reg->acq_drv_Delay(0); // No driving delay cool::Reg->acq_data_Mode(0); // ADC mode (0), Fake data mode (1) cool::Reg->acq_frm_Count(burst_Raw->frame_Count()); // 1 Frame data count cool::Reg->acq_dp_Count(task_Det->detector[0]->chip(0)->dp_Count()); // Total data count // Set data triggering mode (default values) std::cout << "Setting the acquisition triggering mode...\n"; cool::Reg->acq_trg_Mode(0); // Internal trigger cool::Reg->acq_trg_Period(1000); // 10 Hz trigger period } //****************************************************************************** //* * //* Data acquisition functions * //* * //****************************************************************************** //______________________________________________________________________________ void task_DAQ_Main::data_Reset() { // Refit data structures depending on user selection of chip dbg_Print("task_DAQ_Main::data_Reset: resetting data structures", DBG_LVL_FLOW); std::cout << "Driver #" << driver_number << " selected\n"; // Refit for number of frames std::cout << "Nb. of frames " << frames_number << std::endl; burst_Raw->frame_Count(frames_number); burst_Image->frame_Count(frames_number); burst_Pedestal->frame_Count(frames_number); burst_Pedestal2->frame_Count(frames_number); burst_Noise->frame_Count(frames_number); burst_Mask->frame_Count(frames_number); // Clean up common mode vectors common_Mode.clear(); common_ModeNoise.clear(); // Re-initialize common mode vectors for(UInt_t f = 0; f < burst_Image->frame_Count(); f++){ common_Mode.push_back(0); common_ModeNoise.push_back(0); } // Refit data structures depending on chip selection switch( driver_number ){ case 2: burst_Raw->frame_Fit(task_Det->detector[0], frames_number); burst_Image->frame_Fit(task_Det->detector[0], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[0], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[0], frames_number); burst_Noise->frame_Fit(task_Det->detector[0], frames_number); burst_Mask->frame_Fit(task_Det->detector[0], frames_number); break; case 3: burst_Raw->frame_Fit(task_Det->detector[1], frames_number); burst_Image->frame_Fit(task_Det->detector[1], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[1], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[1], frames_number); burst_Noise->frame_Fit(task_Det->detector[1], frames_number); burst_Mask->frame_Fit(task_Det->detector[1], frames_number); break; case 4: burst_Raw->frame_Fit(task_Det->detector[2], frames_number); burst_Image->frame_Fit(task_Det->detector[2], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[2], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[2], frames_number); burst_Noise->frame_Fit(task_Det->detector[2], frames_number); burst_Mask->frame_Fit(task_Det->detector[2], frames_number); break; case 5: std::cout << "Under construction!\n"; case 6: burst_Raw->frame_Fit(task_Det->detector[3], frames_number); burst_Image->frame_Fit(task_Det->detector[3], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[3], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[3], frames_number); burst_Noise->frame_Fit(task_Det->detector[3], frames_number); burst_Mask->frame_Fit(task_Det->detector[3], frames_number); break; case 7: burst_Raw->frame_Fit(task_Det->detector[4], frames_number); burst_Image->frame_Fit(task_Det->detector[4], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[4], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[4], frames_number); burst_Noise->frame_Fit(task_Det->detector[4], frames_number); burst_Mask->frame_Fit(task_Det->detector[4], frames_number); break; case 8: burst_Raw->frame_Fit(task_Det->detector[5], frames_number); burst_Image->frame_Fit(task_Det->detector[5], frames_number); burst_Pedestal->frame_Fit(task_Det->detector[5], frames_number); burst_Pedestal2->frame_Fit(task_Det->detector[5], frames_number); burst_Noise->frame_Fit(task_Det->detector[5], frames_number); burst_Mask->frame_Fit(task_Det->detector[5], frames_number); break; default: // Do nothing break; } // Reset variables for plot rescaling frm_Count = burst_Raw->frame_Count(); col_Count = burst_Raw->frame(0)->layer(0)->dp_col_Count(); row_Count = burst_Raw->frame_Count()*burst_Raw->frame(0)->layer(0)->dp_row_Count(); dp_Count = burst_Raw->frame(0)->layer(0)->dp_Count(); } //______________________________________________________________________________ void task_DAQ_Main::data_Acquire() { // MAIN DATA ACQUISITION FUNCTION dbg_Print("task_DAQ_Main::data_Acquire: retrieving data from DAQ", DBG_LVL_FLOW); // Change button to run mode //btn_Acq[0]->btn_Status( true ); task_GUI->btn_Acq[0]->backColor(0xFF0000); task_GUI->btn_Acq[0]->Text("Stop"); endFlag = 0; // Reset FPGA settings //std::cout << "Resetting FPGA settings " << std::endl; //set_FPGA(); // Refit gui_Maps and gui_Plots task_GUI->map_Event->data_Set(burst_Raw->frame(0)->layer(0)); task_GUI->map_Event->data_Refresh(0, 0, col_Count, row_Count); task_GUI->map_Pedestal->data_Set(burst_Pedestal->frame(0)->layer(0)); task_GUI->map_Pedestal->data_Refresh(0, 0, col_Count, row_Count); task_GUI->map_Noise->data_Set(burst_Noise->frame(0)->layer(0)); task_GUI->map_Noise->data_Refresh(0, 0, col_Count, row_Count); // GRETINA control: 5 is the Gretina ID in the USB chain, // it sends the start bit to the GRETINA controller UShort_t wr_Buff[16] = {5, 0, 0, 0x8801, 0x000, 0x0001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; Int_t wr_Len = 16; // Reset statistics array std::cout << "Resetting Statistics and plots " << std::endl; stats_Reset(); plots_Reset(); // Increase run number if write file and auto run # options are checked if( task_GUI->chk_Acq[0]->chk_Status() == true && task_GUI->chk_Acq[1]->chk_Status() == true ){ // Get current run number run_Number = (UInt_t)task_GUI->num_Acq[3]->num_Val(); // Increase run number task_GUI->num_Acq[3]->num_Val( run_Number + 1 ); } // If write file option checked, setup ntuple for data storage if( task_GUI->chk_Acq[0]->chk_Status() == true ) file_Setup(); // Date timestamp date = time ( NULL ); std::cout << "Acquisition started on " << ctime( &date ) << std::endl; tdate = (long)date; // Acquire as many burst as required by the user burst_Count = (UInt_t)task_GUI->num_Acq[1]->num_Val(); std::cout << "Number of events " << burst_Count << "\n"; UInt_t goodEvents = 0; ////////////////////////// // LOOP OVER THE EVENTS // ////////////////////////// for (UInt_t i = 0 ; i < burst_Count; i++) { // Raise end flag if stop button is pressed if( task_GUI->btn_Acq[0]->btn_Status() == false ) endFlag = 1; if( endFlag ){ std::cout << "Stopping acquisition after " << i << " events\n"; break; } event_Number = i + 1; std::cout << "\nEvent " << event_Number << std::endl; task_GUI->num_Acq[0]->num_Val( event_Number ); // shows current event number tstamp = 0; nspill = 0; ///////////////////////////// // ACQUISITION AND STORAGE // ///////////////////////////// // Acquire data from the firmware cool::Comm->burst_Read(burst_Raw, false, 1000); // If Gretina is the target, trigger the gretina sync bit! if (task_GUI->cmb_DAQ[2]->cbox_Val() == 8) { //std::cout << "Sending gretina start bit...\n"; cool::Comm->raw_Write(wr_Buff, &wr_Len); // Wait for the read thread to be correctly launched } else Sleep(50); // Wait to complete the reading while (cool::Comm->burst_read_Status() != cool::Comm->kbr_Free) { // Use this to process the GUI events pipeline std::cout << "*"; gSystem->ProcessEvents(); // Frees (milliseconds) CPU time. Sleep(50); } // Do all data processing ONLY if everything went fine if (cool::Comm->burst_read_Exited() == cool::Comm->kbr_Free && burst_Raw->frame(0)->layer(0)->dp_Value(0) != 0) { goodEvents++; // Cast Burst (for the moment frame by frame) for(int f = 0; f< burst_Raw->frame_Count(); f++){ *(burst_Image->frame(f)) = *(burst_Raw->frame(f)); } ///////////////////// // DATA PROCESSING // ///////////////////// // Invert data //data_Invert(); // If CDS option checked, calculate CDS (add condition on number of frames!) if( task_GUI->chk_Acq[2]->chk_Status() == true ) data_CDS(); // If pedestal subtract mode, subtract pedestals if( task_GUI->cmb_Acq[0]->cbox_Val() == 2 ) pedestal_Subtract(); // Calculate common mode for the current event if( task_GUI->cmb_Acq[0]->cbox_Val() == 1 || task_GUI->cmb_Acq[0]->cbox_Val() == 2 ) data_CMode(); // Show data task_GUI->map_Event->data_Set(burst_Image->frame(0)->layer(0)); task_GUI->map_Event->data_Refresh(); // 1D online display data_Display(); // If write data option selected, save data in data tree if( task_GUI->chk_Acq[0]->chk_Status() == true ) file_Fill(); // If pedestal run, update pedestal values if( task_GUI->cmb_Acq[0]->cbox_Val() == 1 ) stats_Update(); // Raise end flag at the end of events if( i == burst_Count - 1 ){ std::cout << "\nEnd of " << burst_Count << " events\n"; std::cout << "\nAcquired " << goodEvents << " good events\n"; endFlag = 1; task_GUI->btn_Acq[0]->btn_Status( false ); } // otherwise decrease event counter and continue to next iteration } else { cool::Out->Print("Broken frame\n", LRED); i--; continue; } // Free some time! gSystem->ProcessEvents(); Sleep(50); } // End run over the events ///////////////////////// // PEDESTALS AND NOISE // ///////////////////////// //Calculate pedestals and noise values, in case, and fill corresponding plots if( task_GUI->cmb_Acq[0]->cbox_Val() == 1 ){ stats_Calculate(); stats_Display(); // raise flag that pedestals are available pedFlag = 1; } //////////////////////////////////// // WRITE DATA TO OUTPUT ROOT FILE // //////////////////////////////////// if( task_GUI->chk_Acq[0]->chk_Status() == true ){ data_Write(); // close output file file_Close(); } // Wait mode std::cout << "Entering wait mode...\n"; task_GUI->btn_Acq[0]->backColor(gui_CoolButton::kc_Green); task_GUI->btn_Acq[0]->Text("GO"); } //______________________________________________________________________________ void task_DAQ_Main::stats_Reset() { // Reset statistics arrays dbg_Print("task_DAQ_Main::stats_Reset(): resetting statistics arrays", DBG_LVL_FLOW); if( task_GUI->cmb_Acq[0]->cbox_Val() == 1 ){ std::cout << "Resetting pedestals\n"; pedFlag = 0; for(UInt_t i = 0; i < burst_Raw->frame_Count(); i++){ burst_Pedestal->frame(i)->dp_all_Set(0); burst_Pedestal2->frame(i)->dp_all_Set(0); burst_Noise->frame(i)->dp_all_Set(0); burst_Mask->frame(i)->dp_all_Set(0); } }else{ } } //______________________________________________________________________________ void task_DAQ_Main::plots_Reset() { // Reset event display (always) and statistics plots (if in pedestal run mode dbg_Print("task_DAQ_Main::stats_Reset(): resetting plots", DBG_LVL_FLOW); //task_GUI->eventPlot->Reset(); task_GUI->distPlot->Reset(); if( task_GUI->cmb_Acq[0]->cbox_Val() == 1 ){ task_GUI->pedestalPlot->Reset(); task_GUI->noisePlot->Reset(); } } //______________________________________________________________________________ void task_DAQ_Main::data_Invert() { // Invert analog data from DAQ, or offset digital data dbg_Print("task_DAQ_Main::data_Invert: inverting data", DBG_LVL_FLOW); for(UInt_t i = 0; i < burst_Raw->frame_Count(); i++){ if( data_source == 0 ){ //Invert analog data *burst_Image->frame(i) *= -1; *burst_Image->frame(i) += 16384; }else if( data_source == 1 ){ // Dummy data, do nothing }else if( data_source == 2 ){ // Digital data: just add a level, so that S/N in data analysis is always high *burst_Image->frame(i) *= 1000; }//end if with conditions on data source }// end loop over frames in the burst } //______________________________________________________________________________ void task_DAQ_Main::data_CDS() { // Calculate CDS dbg_Print("task_DAQ_Main::data_CDS: calculating CDS", DBG_LVL_FLOW); for(UInt_t f = 1; f < burst_Raw->frame_Count(); f++){ *burst_Image->frame(f) -= *burst_Image->frame(f - 1); *burst_Image->frame(f - 1) = *burst_Image->frame(f); } } //______________________________________________________________________________ void task_DAQ_Main::pedestal_Subtract() { // Subtract pedestals dbg_Print("task_DAQ_Main::pedestal_Subtract: subtracting pedestals", DBG_LVL_FLOW); for(UInt_t f = 0; f < burst_Raw->frame_Count(); f++){ *burst_Image->frame(f) -= *burst_Pedestal->frame(f); } } //______________________________________________________________________________ void task_DAQ_Main::data_CMode() { // Calculate common mode dbg_Print("task_DAQ_Main::data_CMode: calculating common mode", DBG_LVL_FLOW); Double_t cmode, cmn; for(UInt_t f = 0; f < common_Mode.size(); f++){ common_Mode.at(f) = 0; common_ModeNoise.at(f) = 0; // If common mode option selected, calculate common mode level and noise if( task_GUI->chk_Acq[3]->chk_Status() == true ){ burst_Image->frame(f)->dp_all_Stat(cmode, cmn); common_Mode.at(f) = cmode; common_ModeNoise.at(f) = cmn; } std::cout << "Common mode level " << common_Mode.at(f) << "\n"; } } //______________________________________________________________________________ void task_DAQ_Main::data_Display() { // Show event display plots dbg_Print("task_DAQ_Main::data_Display: showing event display plots", DBG_LVL_FLOW); // gui_Plot: plot either oscilloscope view, column cut or row cut UInt_t plotSel = ((UInt_t)task_GUI->chk_Online[2]->chk_Status() << 2) | ((UInt_t)task_GUI->chk_Online[1]->chk_Status() << 1) | (UInt_t)task_GUI->chk_Online[0]->chk_Status(); std::cout << "plotSel " << plotSel << std::endl; if( plotSel == 1 ){ // Oscilloscope view of all data Double_t* plt_Start = burst_Image->frame(0)->layer(0)->dp_Front(); UInt_t plt_Count = burst_Image->frame(0)->layer(0)->dp_Count(); task_GUI->plt_Event->data_Set(plt_Start, plt_Count, 1); task_GUI->plt_Event->data_Refresh(); }else if( plotSel == 2 ){ // Column slice! UInt_t col_Idx = (UInt_t)task_GUI->num_Online[1]->num_Val(); if (col_Idx < 0) col_Idx = 0; if (col_Idx >= burst_Image->frame(0)->layer(0)->dp_col_Count()){ col_Idx = burst_Image->frame(0)->layer(0)->dp_col_Count() - 1; } UInt_t row_Count = burst_Image->frame(0)->layer(0)->dp_row_Count(); Double_t* line_Start = burst_Image->frame(0)->layer(0)->dp_Front() + row_Count * col_Idx; std::cout << "col_Idx: " << col_Idx << "\n"; std::cout << "line_Start: " << line_Start << "\n"; std::cout << "row_Count: " << row_Count << "\n"; task_GUI->plt_Event->data_Set(line_Start, row_Count, 1); task_GUI->plt_Event->data_Refresh(); }else if( plotSel == 4 ){ // Row slice UInt_t row_Idx = (UInt_t)task_GUI->num_Online[2]->num_Val(); if (row_Idx < 0) row_Idx = 0; if (row_Idx >= burst_Image->frame(0)->layer(0)->dp_row_Count()){ row_Idx = burst_Image->frame(0)->layer(0)->dp_row_Count() - 1; } UInt_t col_Count = burst_Image->frame(0)->layer(0)->dp_col_Count(); Double_t* line_Start = burst_Image->frame(0)->layer(0)->dp_Front() + col_Count * row_Idx; std::cout << "row_Idx: " << row_Idx << "\n"; std::cout << "line_Start: " << line_Start << "\n"; std::cout << "col_Count: " << col_Count << "\n"; task_GUI->plt_Event->data_Set(line_Start, col_Count, 1); task_GUI->plt_Event->data_Refresh(); } // ONLINE PROCESSING HISTOGRAM UInt_t pix_Number = burst_Image->frame(0)->layer(0)->dp_Count(); UInt_t threshold = (UInt_t)task_GUI->num_Online[2]->num_Val(); for(UInt_t f = 0; f < burst_Image->frame_Count(); f++){ for (UInt_t i = 0; i< pix_Number; i++) { Double_t img_Val = burst_Image->frame(f)->layer(0)->dp_Value(i); UInt_t img_Row = burst_Image->frame(f)->layer(0)->dp_Row(i); UInt_t img_Col = burst_Image->frame(f)->layer(0)->dp_Col(i); Double_t noi_Val = burst_Noise->frame(f)->layer(0)->dp_Value(i); UShort_t msk_Val = burst_Mask->frame(f)->layer(0)->dp_Value(i); // Fill online process histogram (only in pedestal subtraction mode) if( task_GUI->cmb_Acq[0]->cbox_Val() == 2 ){ // Online processing of data for distPlot if( noi_Val>0 && noi_Val<10 && (img_Val - common_Mode[f])/(noi_Val)> threshold ){ // WARNING!!! Check usage of dp_Value() burst_Mask->frame(f)->layer(0)->dp_Value(i, msk_Val + 1); if( msk_Val<25 && event_Number>100 && img_Col>5 && img_Row<1020) task_GUI->distPlot->Fill(img_Val - common_Mode[f]); } } } // End loop over array entries } // End loop over frames if( task_GUI->chk_Online[3]->chk_Status() == true ){ task_GUI->plotCanvas->Root()->GetCanvas()->cd(); task_GUI->distPlot->Draw(); } // Update canvas task_GUI->plotCanvas->Root()->GetCanvas()->Update(); } //______________________________________________________________________________ void task_DAQ_Main::data_Write() { // Write data to output file dbg_Print("task_DAQ_Main::data_Write: writing data to output file", DBG_LVL_FLOW); // Write info in the header header[0] = 7; // ChipId header[1] = (UInt_t)task_GUI->num_Acq[3]->num_Val(); // Run number header[2] = (UInt_t)task_GUI->num_DAQ[2]->num_Val(); // Number of frames header[3] = burst_Raw->frame(0)->layer(0)->dp_row_Count(); header[4] = burst_Raw->frame(0)->layer(0)->dp_col_Count(); // header[5]: CDS data? if( task_GUI->chk_Acq[2]->chk_Status() == true ){ // CDS = 1, NO CDS = 0 header[5] = 1; }else{ header[5] = 0; } // header[6]: ped subtracted? if(pedFlag){ header[6] = 1; // 1 if pedestal subtracted data, 0 otherwise }else{ header[6] = 0; } // header[7,8]: first row and column header[7] = 0; // First row header[8] = 0; // First column // header[9]: data source if( task_GUI->cmb_DAQ[3]->cbox_Val() == 0 ){ header[9] = 0; // ADC data }else if( task_GUI->cmb_DAQ[3]->cbox_Val() == 2){ header[9] = 0; // Digital data }else{ header[9] = 0; } // header[10]: date, which is long and is split over two integers header[10] = tdate; for(int h=12; h<50; h++){ header[h] = 0; } // Make physical copy of pedestals and noise arrays for(UInt_t f = 0; f < burst_Pedestal->frame_Count(); f++){ for(int i = 0; i < NPixels ; i++ ){ ped[i] = burst_Pedestal->frame(f)->layer(0)->dp_Value(i); noi[i] = burst_Noise->frame(f)->layer(0)->dp_Value(i); } } // Fill the header tree std::cout << "Filling headertree...\n"; headertree->Fill(); // Write header tree std::cout << "Writing headertree...\n"; headertree->Write(); headertree->Print(); // Write data tree std::cout << "Writing datatree...\n"; datatree->Write(); datatree->Print(); // Write plots task_GUI->pedestalPlot->Write(); task_GUI->noisePlot->Write(); } //______________________________________________________________________________ void task_DAQ_Main::stats_Update() { // Update statistics arrays dbg_Print("task_DAQ_Main::stats_Update: updating statistics arrays", DBG_LVL_FLOW); for(UInt_t f = 0; f < burst_Pedestal->frame_Count(); f++){ *(burst_Pedestal->frame(f)) += *(burst_Image->frame(f)); *(burst_Pedestal2->frame(f)) += burst_Image->frame(f)->dp_all_Pow(2); } } //______________________________________________________________________________ void task_DAQ_Main::stats_Calculate() { // Calculate pedestal and noise values dbg_Print("task_DAQ_Main::stats_Calculate: calculating pedestals and noise", DBG_LVL_FLOW); for(UInt_t f = 0; f < burst_Pedestal->frame_Count(); f++){ // Calculate and std::cout << "Dividing by" << burst_Count << "\n";; *(burst_Pedestal->frame(f)) /= burst_Count; *(burst_Pedestal2->frame(f)) /= burst_Count; // Temporary container data_Frame* frame_Temp = new data_Frame; *frame_Temp = *(burst_Pedestal->frame(f)); frame_Temp->dp_all_Pow(2); *(burst_Pedestal2->frame(f)) -= *frame_Temp; *(burst_Noise->frame(f)) = *(burst_Pedestal2->frame(f)); burst_Noise->frame(0)->dp_all_Sqr(); delete frame_Temp; } } //______________________________________________________________________________ void task_DAQ_Main::stats_Display() { // Display pedestals and noise maps/distributions dbg_Print("task_DAQ_Main::stats_Display: displaying pedestals and noise", DBG_LVL_FLOW); // Fill statistics plots for(UInt_t f = 0; f < burst_Pedestal->frame_Count(); f++){ for (UInt_t i = 0; i< burst_Pedestal->frame(0)->layer(0)->dp_Count(); i++) { Double_t ped_Val = burst_Pedestal->frame(f)->layer(0)->dp_Value(i); Double_t noi_Val = burst_Noise->frame(f)->layer(0)->dp_Value(i); // Debug if (i < 10) std::cout <pedestalPlot->Fill(ped_Val); task_GUI->noisePlot->Fill(noi_Val); } } // Draw statistics plots task_GUI->pedCanvas->Root()->GetCanvas()->cd(); task_GUI->pedestalPlot->Draw(); task_GUI->noiCanvas->Root()->GetCanvas()->cd(); task_GUI->noisePlot->Draw(); // Update the canvas with statistics plots task_GUI->pedCanvas->Root()->GetCanvas()->Update(); task_GUI->noiCanvas->Root()->GetCanvas()->Update(); // Draw pedestal and noise maps task_GUI->map_Pedestal->data_Set(burst_Pedestal->frame(0)->layer(0)); task_GUI->map_Pedestal->data_Refresh(); task_GUI->map_Noise->data_Set(burst_Noise->frame(0)->layer(0)); task_GUI->map_Noise->data_Refresh(); } //______________________________________________________________________________ void task_DAQ_Main::file_Setup() { // Setup output ROOT file dbg_Print("task_DAQ_Main::file_Setup: setting up output ROOT file", DBG_LVL_FLOW); NPixels = (burst_Raw->frame_Count())*(burst_Raw->frame(0)->layer(0)->dp_Count()); std::cout << "NPixels " << NPixels << std::endl; img_data = new Double_t[NPixels]; ped = new Double_t[NPixels]; noi = new Double_t[NPixels]; tstamp = 0; nspill = 0; filepath = task_GUI->txt_Acq[0]->txt_Val(); sprintf(filename,"%s_run%u.root", filepath, (UInt_t)task_GUI->num_Acq[3]->num_Val()); std::cout << "Save in file " << filename << "\n"; datafile = new TFile(filename,"RECREATE"); datafile->SetCompressionLevel((UInt_t)task_GUI->num_Acq[2]->num_Val()); std::cout << "File compression level set to " << (UInt_t)task_GUI->num_Acq[2]->num_Val() << "\n"; headertree = new TTree("headertree", "Header tree"); headertree->Branch("NPixels",&NPixels,"NPixels/I"); headertree->Branch("Header", &header, "header[50]/I"); headertree->Branch("Pedestal", (void*)ped, "ped[NPixels]/D"); headertree->Branch("Noise", (void*)noi, "noi[NPixels]/D"); headertree->SetDirectory(datafile); datatree = new TTree("datatree","Data tree"); datatree->Branch("NPixels",&NPixels,"NPixels/I"); datatree->Branch("Data",(void*)img_data,"img_data[NPixels]/D"); datatree->Branch("Event",&nevent,"nevent/I"); datatree->Branch("Timestamp",&tstamp,"tstamp/I"); datatree->Branch("Spill",&nspill,"nspill/I"); datatree->SetDirectory(datafile); } //______________________________________________________________________________ void task_DAQ_Main::file_Fill() { // Fill ROOT file dbg_Print("task_DAQ_Main::file_Fill: filling ROOT file", DBG_LVL_FLOW); // Make physical copy of the image_Array for( int f = 0; f < burst_Image->frame_Count(); f++ ){ for(int i = 0; i < NPixels ; i++ ) img_data[i + f*NPixels] = burst_Image->frame(f)->layer(0)->dp_Value(i); } nevent = event_Number; tstamp = 0; nspill = 0; // Fill the ntuple datatree->Fill(); } //______________________________________________________________________________ void task_DAQ_Main::file_Close() { // Close output ROOT file dbg_Print("task_DAQ_Main::file_Close: closing output ROOT file", DBG_LVL_FLOW); datafile->Close(); }