Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <CAENVMElib.h>
- #include <iostream>
- #include <stdexcept>
- #include <unistd.h>
- using namespace std;
- const string error_codes[] = {"Success","Bus Error","Comm Error","Generic Error","Invalid Param","Timeout Error"};
- #define S(x) #x
- #define S_(x) S(x)
- #define S__LINE__ S_(__LINE__)
- #define SAFE(call) { \
- const int err = call; \
- if (err) throw std::runtime_error("CAEN Error (" + error_codes[-err] + ") at " __FILE__ ":" S__LINE__ " " #call); \
- }
- class VMEBridge {
- public:
- VMEBridge(int link, int board) {
- SAFE(CAENVME_Init(cvV1718,link,board,&handle));
- }
- virtual ~VMEBridge() {
- SAFE(CAENVME_End(handle));
- }
- inline void write32(uint32_t addr, uint32_t data) {
- SAFE(CAENVME_WriteCycle(handle, addr, &data, cvA32_U_DATA, cvD32));
- usleep(10000);
- }
- inline uint32_t read32(uint32_t addr) {
- uint32_t read;
- usleep(1);
- SAFE(CAENVME_ReadCycle(handle, addr, &read, cvA32_U_DATA, cvD32));
- return read;
- }
- inline void write16(uint32_t addr, uint32_t data) {
- SAFE(CAENVME_WriteCycle(handle, addr, &data, cvA32_U_DATA, cvD16));
- usleep(10000);
- }
- inline uint32_t read16(uint32_t addr) {
- uint32_t read;
- SAFE(CAENVME_ReadCycle(handle, addr, &read, cvA32_U_DATA, cvD16));
- return read;
- }
- inline uint32_t readBLT(uint32_t addr, void *buffer, uint32_t size) {
- uint32_t bytes;
- CAENVME_MBLTReadCycle(handle, addr, buffer, size, cvA32_U_MBLT, (int*)&bytes);
- return bytes;
- }
- protected:
- int handle;
- };
- typedef struct {
- //REG_CHANNEL_ENABLE_MASK
- uint32_t enabled; // 1 bit
- //REG_GLOBAL_TRIGGER_MASK
- uint32_t global_trigger; // 1 bit
- //REG_TRIGGER_OUT_MASK
- uint32_t trg_out; // 1 bit
- //REG_RECORD_LENGTH
- uint32_t record_length; // 16* bit
- //REG_DYNAMIC_RANGE
- uint32_t dynamic_range; // 1 bit
- //REG_NEV_AGGREGATE
- uint32_t ev_per_buffer; // 10 bit
- //REG_PRE_TRG
- uint32_t pretrigger; // 9* bit
- //REG_LONG_GATE
- uint32_t long_gate; // 12 bit
- //REG_SHORT_GATE
- uint32_t short_gate; // 12 bit
- //REG_PRE_GATE
- uint32_t gate_offset; // 8 bit
- //REG_DPP_TRG_THRESHOLD
- uint32_t trg_threshold; // 12 bit
- //REG_BASELINE_THRESHOLD
- uint32_t fixed_baseline; // 12 bit
- //REG_SHAPED_TRIGGER_WIDTH
- uint32_t shaped_trigger_width; // 10 bit
- //REG_TRIGGER_HOLDOFF
- uint32_t trigger_holdoff; // 10* bit
- //REG_DPP_CTRL
- uint32_t charge_sensitivity; // 3 bit (see docs)
- uint32_t pulse_polarity; // 1 bit (0->positive, 1->negative)
- uint32_t trigger_config; // 2 bit (see docs)
- uint32_t baseline_mean; // 3 bit (fixed, 16, 64, 256, 1024)
- uint32_t self_trigger; // 1 bit (0->enabled, 1->disabled)
- //REG_DC_OFFSET
- uint32_t dc_offset; // 16 bit (-1V to 1V)
- } V1730_chan_config;
- typedef struct {
- //REG_CONFIG
- uint32_t dual_trace; // 1 bit
- uint32_t analog_probe; // 2 bit (see docs)
- uint32_t oscilloscope_mode; // 1 bit
- uint32_t digital_virt_probe_1; // 3 bit (see docs)
- uint32_t digital_virt_probe_2; // 3 bit (see docs)
- //REG_GLOBAL_TRIGGER_MASK
- uint32_t coincidence_window; // 3 bit
- uint32_t global_majority_level; // 3 bit
- uint32_t external_global_trigger; // 1 bit
- uint32_t software_global_trigger; // 1 bit
- //REG_TRIGGER_OUT_MASK
- uint32_t out_logic; // 2 bit (OR,AND,MAJORITY)
- uint32_t out_majority_level; // 3 bit
- uint32_t external_trg_out; // 1 bit
- uint32_t software_trg_out; // 1 bit
- //REG_BUFF_ORG
- uint32_t buff_org;
- //REG_READOUT_BLT_AGGREGATE_NUMBER
- uint16_t max_board_agg_blt;
- } V1730_card_config;
- class V1730_DPP_PSD {
- //system wide
- #define REG_CONFIG 0x8000
- #define REG_CONFIG_SET 0x8004
- #define REG_CONFIG_CLEAR 0x8008
- #define REG_BUFF_ORG 0x800C
- #define REG_FRONT_PANEL_CONTROL 0x811C
- #define REG_DUMMY 0xEF20
- #define REG_SOFTWARE_RESET 0xEF24
- #define REG_SOFTWARE_CLEAR 0xEF28
- #define REG_BOARD_CONFIGURATION_RELOAD 0xEF34
- //per channel, or with 0x0n00
- #define REG_RECORD_LENGTH 0x1020
- #define REG_DYNAMIC_RANGE 0x1024
- #define REG_NEV_AGGREGATE 0x1034
- #define REG_PRE_TRG 0x1038
- #define REG_SHORT_GATE 0x1054
- #define REG_LONG_GATE 0x1058
- #define REG_PRE_GATE 0x105C
- #define REG_DPP_TRG_THRESHOLD 0x1060
- #define REG_BASELINE_THRESHOLD 0x1064
- #define REG_SHAPED_TRIGGER_WIDTH 0x1070
- #define REG_TRIGGER_HOLDOFF 0x1074
- #define REG_DPP_CTRL 0x1080
- #define REG_TRIGGER_CTRL 0x1084
- #define REG_DC_OFFSET 0x1098
- //acquisition
- #define REG_ACQUISITION_CONTROL 0x8100
- #define REG_ACQUISITION_STATUS 0x8104
- #define REG_SOFTWARE_TRIGGER 0x8108
- #define REG_GLOBAL_TRIGGER_MASK 0x810C
- #define REG_TRIGGER_OUT_MASK 0x8110
- #define REG_CHANNEL_ENABLE_MASK 0x8120
- //readout
- #define REG_EVENT_SIZE 0x814C
- #define REG_READOUT_CONTROL 0xEF00
- #define REG_READOUT_STATUS 0xEF04
- #define REG_VME_ADDRESS_RELOCATION 0xEF10
- #define REG_READOUT_BLT_AGGREGATE_NUMBER 0xEF1C
- public:
- V1730_DPP_PSD(VMEBridge &_bridge, uint32_t _baseaddr) : bridge(_bridge), baseaddr(_baseaddr) {
- //These are "do nothing" defaults, testparams() will set up the acquisition
- card.dual_trace = 0; // 1 bit
- card.analog_probe = 0; // 2 bit (see docs)
- card.oscilloscope_mode = 1; // 1 bit
- card.digital_virt_probe_1 = 0; // 3 bit (see docs)
- card.digital_virt_probe_2 = 0; // 3 bit (see docs)
- card.coincidence_window = 1; // 3 bit
- card.global_majority_level = 0; // 3 bit
- card.external_global_trigger = 0; // 1 bit
- card.software_global_trigger = 0; // 1 bit
- card.out_logic = 0; // 2 bit (OR,AND,MAJORITY)
- card.out_majority_level = 0; // 3 bit
- card.external_trg_out = 0; // 1 bit
- card.software_trg_out = 0; // 1 bit
- card.max_board_agg_blt = 500;
- for (uint32_t ch = 0; ch < 16; ch++) {
- chans[ch].enabled = 0; //1 bit
- chans[ch].global_trigger = 0; // 1 bit
- chans[ch].trg_out = 0; // 1 bit
- chans[ch].record_length = 80; // 16* bit
- chans[ch].dynamic_range = 0; // 1 bit
- chans[ch].ev_per_buffer = 10; // 10 bit
- chans[ch].pretrigger = 50; // 9* bit
- chans[ch].long_gate = 20; // 12 bit
- chans[ch].short_gate = 10; // 12 bit
- chans[ch].gate_offset = 5; // 8 bit
- chans[ch].trg_threshold = 33; // 12 bit
- chans[ch].fixed_baseline = 0; // 12 bit
- chans[ch].shaped_trigger_width = 10; // 10 bit
- chans[ch].trigger_holdoff = 10; // 10* bit
- chans[ch].charge_sensitivity = 000; // 3 bit (see docs)
- chans[ch].pulse_polarity = 1; // 1 bit (0->positive, 1->negative)
- chans[ch].trigger_config = 0; // 2 bit (see docs)
- chans[ch].baseline_mean = 3; // 3 bit (fixed,16,64,256,1024)
- chans[ch].self_trigger = 1; // 1 bit (0->enabled, 1->disabled)
- chans[ch].dc_offset = 0x8000; // 16 bit (-1V to 1V)
- }
- }
- virtual ~V1730_DPP_PSD() {
- //Fully reset the board just in case
- write32(REG_BOARD_CONFIGURATION_RELOAD,0);
- }
- void testparams() {
- card.external_global_trigger = 1;
- chans[0].enabled = 1;
- //chans[0].pulse_polarity = 0;
- //chans[0].global_trigger = 1;
- //chans[0].self_trigger = 1;
- //chans[1].enabled = 1;
- //chans[2].enabled = 1;
- //chans[3].enabled = 1;
- //chans[4].enabled = 1;
- //chans[5].enabled = 1;
- //chans[6].enabled = 1;
- //chans[7].enabled = 1;
- //chans[8].enabled = 1;
- //chans[9].enabled = 1;
- //chans[10].enabled = 1;
- //chans[11].enabled = 1;
- //chans[12].enabled = 1;
- //chans[13].enabled = 1;
- //chans[14].enabled = 1;
- //chans[15].enabled = 1;
- }
- void program() { //FIXME validate bit fields!!!
- //used to build bit fields
- uint32_t data;
- cout << "\treset" << endl;
- //Fully reset the board just in case
- write32(REG_BOARD_CONFIGURATION_RELOAD,0);
- cout << "\tttl" << endl;
- //Set TTL logic levels, ignore LVDS and debug settings
- write32(REG_FRONT_PANEL_CONTROL,1);
- cout << "\tconfig" << endl;
- data = (1 << 4)
- | (1 << 8)
- | (card.dual_trace << 11)
- | (card.analog_probe << 12)
- | (card.oscilloscope_mode << 16)
- | (1 << 17)
- | (1 << 18)
- | (1 << 19)
- | (card.digital_virt_probe_1 << 23)
- | (card.digital_virt_probe_2 << 26);
- write32(REG_CONFIG,data);
- //build masks while configuring channels
- uint32_t channel_enable_mask = 0;
- uint32_t global_trigger_mask = (card.coincidence_window << 20)
- | (card.global_majority_level << 24)
- | (card.external_global_trigger << 30)
- | (card.software_global_trigger << 31);
- uint32_t trigger_out_mask = (card.out_logic << 8)
- | (card.out_majority_level << 10)
- | (card.external_trg_out << 30)
- | (card.software_trg_out << 31);
- //keep track of the size of the buffers for each memory location
- uint32_t buffer_sizes[8] = { 0, 0, 0, 0, 0, 0, 0, 0}; //in locations
- //keep track of how to config the local triggers
- uint32_t local_logic[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- for (int ch = 0; ch < 16; ch++) {
- channel_enable_mask |= (chans[ch].enabled << ch);
- global_trigger_mask |= (chans[ch].global_trigger << (ch/2));
- trigger_out_mask |= (chans[ch].trg_out << (ch/2));
- cout << "\tch" << ch << endl;
- if (ch % 2 == 0) { //memory shared between pairs
- if (chans[ch].global_trigger) {
- if (chans[ch+1].global_trigger) {
- local_logic[ch/2] = 3;
- } else {
- local_logic[ch/2] = 1;
- }
- } else {
- if (chans[ch+1].global_trigger) {
- local_logic[ch/2] = 2;
- } else {
- local_logic[ch/2] = 0;
- }
- }
- cout << "\t\trecord" << endl;
- if (chans[ch].record_length > 65535) throw runtime_error("Number of samples exceeds 4095");
- data = chans[ch].record_length%8 ? chans[ch].record_length/8+1 : chans[ch].record_length/8;
- write32(REG_RECORD_LENGTH|(ch<<8),data);
- chans[ch].record_length = read32(REG_RECORD_LENGTH|(ch<<8))*8;
- } else {
- chans[ch].record_length = chans[ch-1].record_length;
- chans[ch].ev_per_buffer = chans[ch-1].ev_per_buffer;
- }
- cout << "\t\tbuffer" << endl;
- if (chans[ch].ev_per_buffer < 2) throw runtime_error("Number of events per channel buffer must be at least 2");
- if (chans[ch].ev_per_buffer > 1023) throw runtime_error("Number of events per channel buffer exceeds 1023");
- write32(REG_NEV_AGGREGATE|(ch<<8),chans[ch].ev_per_buffer);
- if (chans[ch].enabled) {
- buffer_sizes[ch/2] = (2 + chans[ch].record_length/8)*chans[ch].ev_per_buffer;
- }
- cout << "\t\tpre_trig" << endl;
- if (chans[ch].pretrigger > 2044) throw runtime_error("Pretrigger samples exceeds 2044");
- write32(REG_PRE_TRG|(ch<<8),chans[ch].pretrigger/4);
- cout << "\t\tlong_gate" << endl;
- if (chans[ch].short_gate > 4095) throw runtime_error("Short gate samples exceeds 4095");
- write32(REG_SHORT_GATE|(ch<<8),chans[ch].short_gate);
- cout << "\t\tshort_gate" << endl;
- if (chans[ch].long_gate > 4095) throw runtime_error("Long gate samples exceeds 4095");
- write32(REG_LONG_GATE|(ch<<8),chans[ch].long_gate);
- cout << "\t\tgate_offset" << endl;
- if (chans[ch].gate_offset > 255) throw runtime_error("Gate offset samples exceeds 255");
- if (chans[ch].pretrigger < chans[ch].gate_offset + 19) throw runtime_error("Gate offset and pretrigger relationship violated");
- write32(REG_PRE_GATE|(ch<<8),chans[ch].gate_offset);
- cout << "\t\ttrig_threshold" << endl;
- if (chans[ch].trg_threshold > 4095) throw runtime_error("Trigger threshold exceeds 4095");
- write32(REG_DPP_TRG_THRESHOLD|(ch<<8),chans[ch].trg_threshold);
- cout << "\t\tfixed_baseleine" << endl;
- if (chans[ch].fixed_baseline > 4095) throw runtime_error("Fixed baseline exceeds 4095");
- write32(REG_BASELINE_THRESHOLD|(ch<<8),chans[ch].fixed_baseline);
- cout << "\t\tshaped_trigger_width" << endl;
- if (chans[ch].shaped_trigger_width > 1023) throw runtime_error("Shaped trigger width exceeds 1023");
- write32(REG_SHAPED_TRIGGER_WIDTH|(ch<<8),chans[ch].shaped_trigger_width);
- cout << "\t\ttrigger_holdoff" << endl;
- if (chans[ch].trigger_holdoff > 4092) throw runtime_error("Trigger holdoff width exceeds 4092");
- write32(REG_TRIGGER_HOLDOFF|(ch<<8),chans[ch].trigger_holdoff/4);
- cout << "\t\tdpp_ctrl" << endl;
- data = (chans[ch].charge_sensitivity)
- | (chans[ch].pulse_polarity << 16)
- | (chans[ch].trigger_config << 18)
- | (chans[ch].baseline_mean << 20)
- | (chans[ch].self_trigger << 24);
- write32(REG_DPP_CTRL|(ch<<8),data);
- cout << "\t\ttrigger_ctrl" << endl;
- data = local_logic[ch/2] | (1<<2);
- write32(REG_TRIGGER_CTRL|(ch<<8),data);
- cout << "\t\tdc_offset" << endl;
- if (chans[ch].dc_offset > 65535) throw runtime_error("DC Offset cannot exceed 0xFFFF");
- write32(REG_DC_OFFSET|(ch<<8),chans[ch].dc_offset);
- }
- cout << "\tchannel_enable_mask" << endl;
- write32(REG_CHANNEL_ENABLE_MASK,channel_enable_mask);
- cout << "\tglobal_trigger_mask" << endl;
- write32(REG_GLOBAL_TRIGGER_MASK,global_trigger_mask);
- cout << "\ttrigger_out_mask" << endl;
- write32(REG_TRIGGER_OUT_MASK,trigger_out_mask);
- cout << "\tbuff_org" << endl;
- uint32_t largest_buffer = 0;
- for (int i = 0; i < 8; i++) if (largest_buffer < buffer_sizes[i]) largest_buffer = buffer_sizes[i];
- const uint32_t total_locations = 640000/8;
- const uint32_t num_buffers = total_locations/largest_buffer;
- uint32_t shifter = num_buffers;
- for (card.buff_org = 0; shifter != 1; shifter = shifter >> 1, card.buff_org++);
- if (1 << card.buff_org < num_buffers) card.buff_org++;
- if (card.buff_org > 0xA) card.buff_org = 0xA;
- if (card.buff_org < 0x2) card.buff_org = 0x2;
- cout << "Largest buffer: " << largest_buffer << " loc\nDesired buffers: " << num_buffers << "\nProgrammed buffers: " << (1<<card.buff_org) << endl;
- write32(REG_BUFF_ORG,card.buff_org);
- //Set max board aggregates to transver per readout
- write16(REG_READOUT_BLT_AGGREGATE_NUMBER,card.max_board_agg_blt);
- //Enable VME BLT readout
- write16(REG_READOUT_CONTROL,0);
- }
- void startAcquisition() {
- write32(REG_ACQUISITION_CONTROL,1<<2);
- }
- void stopAcquisition() {
- write32(REG_ACQUISITION_CONTROL,0);
- }
- bool readoutReady() {
- return read32(REG_ACQUISITION_STATUS) & (1 << 3);
- }
- size_t readoutBLT(char *buffer, size_t buffer_size) {
- size_t offset = 0, total = 0;
- while (readoutReady()) {
- uint32_t next = read32(REG_EVENT_SIZE);
- total += 4*next;
- if (offset+total > buffer_size) throw runtime_error("Readout buffer too small!");
- size_t lastoff = offset;
- while (offset < total) {
- size_t remaining = total-offset, read;
- if (remaining > 4090) {
- read = readBLT(0x0000, buffer+offset, 4090);
- } else {
- remaining = 8*(remaining%8 ? remaining/8+1 : remaining/8); // needs to be multiples of 8 (64bit)
- read = readBLT(0x0000, buffer+offset, remaining);
- }
- offset += read;
- if (!read) {
- cout << "\tfailed event size " << offset-lastoff << " / " << next*4 << endl;
- break;
- }
- }
- }
- return total;
- }
- inline void write16(uint32_t reg, uint32_t data) {
- bridge.write16(baseaddr|reg,data);
- }
- inline uint32_t read16(uint32_t reg) {
- return bridge.read16(baseaddr|reg);
- }
- inline void write32(uint32_t reg, uint32_t data) {
- bridge.write32(baseaddr|reg,data);
- }
- inline uint32_t read32(uint32_t reg) {
- return bridge.read32(baseaddr|reg);
- }
- inline uint32_t readBLT(uint32_t addr, void *buffer, uint32_t size) {
- return bridge.readBLT(baseaddr|addr,buffer,size);
- }
- protected:
- VMEBridge &bridge;
- uint32_t baseaddr;
- V1730_card_config card;
- V1730_chan_config chans[16];
- };
- size_t event_counter;
- size_t chanagg_counter;
- size_t boardagg_counter;
- size_t readout_counter;
- uint32_t* decode_chan_agg(uint32_t *chanagg) {
- const bool format_flag = chanagg[0] & 0x80000000;
- if (!format_flag) throw runtime_error("Channel format not found");
- chanagg_counter++;
- const uint32_t size = chanagg[0] & 0x7FFF;
- const uint32_t format = chanagg[1];
- const uint32_t samples = (format & 0xFFF)*8;
- if (!format_flag) cout << samples << endl;
- //cout << "\tc: " << size << ' ' << samples << endl;
- /*
- const bool dualtrace_enable = format & (1<<31);
- const bool charge_enable =format & (1<<30);
- const bool time_enable = format & (1<<29);
- const bool baseline_enable = format & (1<<28);
- const bool waveform_enable = format & (1<<27);
- const uint32_t extras = (format >> 24) & 0x7;
- const uint32_t analog_probe = (format >> 22) & 0x3;
- const uint32_t digital_probe_2 = (format >> 19) & 0x7;
- const uint32_t digital_probe_1 = (format >> 16) & 0x7;
- */
- for (uint32_t *event = chanagg+2; event-chanagg+1 < size; event += samples/2+3) {
- event_counter++;
- const bool oddch = event[0] & 0x80000000;
- const uint32_t timetag = event[0] & 0x7FFFFFFF;
- //cout << "\t\te: " << oddch << ' ' << timetag << endl;
- for (uint32_t *word = event, sample = 0; sample < samples; word++, sample+=2) {
- uint16_t sample0 = *word & 0x3FFF;
- uint8_t dp10 = (*word >> 14) & 0x1;
- uint8_t dp20 = (*word >> 15) & 0x1;
- uint16_t sample1 = (*word >> 16) & 0x3FFF;
- uint8_t dp11 = (*word >> 30) & 0x1;
- uint8_t dp21 = (*word >> 31) & 0x1;
- }
- }
- return chanagg + size;
- }
- uint32_t* decode_board_agg(uint32_t *boardagg) {
- if (boardagg[0] == 0xFFFFFFFF) {
- boardagg++; //sometimes padded
- cout << "padded\n";
- }
- if ((boardagg[0] & 0xF0000000) != 0xA0000000)
- throw runtime_error("Board aggregate missing tag");
- boardagg_counter++;
- uint32_t size = boardagg[0] & 0x0FFFFFFF;
- const uint32_t board = (boardagg[1] >> 28) & 0xF;
- const bool fail = boardagg[1] & (1 << 26);
- const uint32_t pattern = (boardagg[1] >> 8) & 0x7FFF;
- const uint32_t mask = boardagg[1] & 0xFF;
- const uint32_t count = boardagg[2] & 0x7FFFFF;
- const uint32_t timetag = boardagg[3];
- //cout << "b: " << count << ' ' << timetag << hex << mask << dec << endl;
- uint32_t *chans = boardagg+4;
- for (uint32_t gr = 0; gr < 8; gr++) {
- if (mask & (1 << gr)) {
- chans = decode_chan_agg(chans);
- }
- }
- return boardagg+size;
- }
- int main(int argc, char **argv) {
- cout << "Opening VME link..." << endl;
- VMEBridge bridge(0,0);
- V1730_DPP_PSD dgtz(bridge,0xAAAA0000);
- //load the test paramters (temp)
- dgtz.testparams();
- cout << "Programming Digitizer..." << endl;
- dgtz.program();
- cout << "Starting acquisition..." << endl;
- dgtz.startAcquisition();
- size_t buffer_size = 100*1024*1024;
- char *buffer = new char[buffer_size];
- event_counter = chanagg_counter = boardagg_counter = readout_counter = 0;
- while (true) {
- while (!dgtz.readoutReady());
- size_t readout_size = dgtz.readoutBLT(buffer,buffer_size);
- readout_counter++;
- cout << "readout " << readout_counter << " : " << readout_size << " bytes" << endl;
- uint32_t *next = (uint32_t*)buffer, *start = (uint32_t*)buffer;
- while (((next = decode_board_agg(next)) - start + 1)*4 < readout_size) {
- }
- cout << "e: " << event_counter << " / c: " << chanagg_counter << " / b: " << boardagg_counter << endl;
- }
- delete [] buffer;
- //Stop Aquisition
- dgtz.stopAcquisition();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement