/* * vetrocRateTest.cpp * * Created on: Nov 2, 2017 * Author: Hovanes Egiyan */ #include #include #include #include #include #include using namespace std; extern "C" { #include "jvme.h" #include "vetrocLib.h" } #define VETROC_SLOT 2 //#define USEDMA struct vetroc_data_struct { // We're told the VETROC is similar to FADC, so I copied that struct; // but surely some of this is not used unsigned int new_type; unsigned int type; unsigned int slot_id_hd; unsigned int slot_id_tr; unsigned int slot_id_evh; unsigned int n_evts; unsigned int blk_num; unsigned int modID; unsigned int PL; unsigned int NSB; unsigned int NSA; unsigned int n_words; unsigned int evt_num_1; unsigned int evt_num_2; unsigned int time_now; unsigned int time_1; unsigned int time_2; unsigned int time_3; unsigned int time_4; unsigned int chan; unsigned int width; unsigned int valid_1; unsigned int adc_1; unsigned int valid_2; unsigned int adc_2; unsigned int over; unsigned int adc_sum; unsigned int pulse_num; unsigned int thres_bin; unsigned int quality; unsigned int integral; unsigned int time; unsigned int chan_a; unsigned int source_a; unsigned int chan_b; unsigned int source_b; unsigned int group; unsigned int time_coarse; unsigned int time_fine; unsigned int vmin; unsigned int vpeak; unsigned int trig_type_int; unsigned int trig_state_int; unsigned int evt_num_int; unsigned int err_status_int; unsigned int scaler_data_words; }; /* global variables */ extern int nvetroc; /* Number of VETROCs in Crate */ static unsigned int vetrocSlotMask; //static unsigned int MAXVETROCWORDS = 10000; //static unsigned int MAXVETROCWORDS = 46; int block_level = 1; double pulseFrequency = 2000.0; double dutyCycle = 0.5; //int block_level = 255; int read_stat = 0; //unsigned int *tdcbuf; extern DMANODE *the_event; extern unsigned int *dma_dabufp; int i_print = 0; struct vetroc_data_struct vetroc_data; unsigned long NumberOfEvents = 600000; DMA_MEM_ID vetrocVME_IN; DMA_MEM_ID vetrocVME_OUT; void usage( int ix ); void setup(); void createTrigger(); void getData(); void vetrocDataDecode( unsigned int data ); int main( int argc, char *argv[] ) { int vetroc_addr, iflag, nvetroc; int narg; printf( "argc %d \n", argc ); if ( argc < 2 ) { usage( 0 ); exit( 0 ); } narg = atoi( argv[1] ); printf( "narg = %d \n", narg ); if ( narg < 1 || narg > 3 ) { usage( 1 ); exit( 0 ); } // tdcbuf = (int *) malloc( MAXVETROCWORDS * sizeof(unsigned int) ); // tdcbuf = (unsigned int*) ( malloc( MAXVETROCWORDS * sizeof(unsigned int) ) ); vmeOpenDefaultWindows(); vmeBusLock(); if ( narg >= 1 ) setup(); for ( unsigned iEvent = 0; iEvent < NumberOfEvents; iEvent++ ) { if ( iEvent % 1000 == 0 ) { cout << "Working on event number " << iEvent << endl; i_print = 1; } if ( narg >= 2 ) createTrigger(); if ( narg == 3 ) getData(); i_print = 0; } dmaPFreeAll(); vmeBusUnlock(); vmeCloseDefaultWindows(); return 0; } void usage( int iwhich ) { if ( iwhich == 0 ) printf( "Need 1 arg, which tells what to do \n" ); if ( iwhich == 1 ) printf( "Arg must be within a range \n" ); printf( " usage: ./vetrocRatetest N \n" ); printf( " N >= 1, initialize then exit \n" ); printf( " N >= 2, look for a trigger \n" ); printf( " N = 3, read data into a buffer and print it \n" ); } void setupDMA() { // vetrocVME_IN = dmaPCreate( "vmeIN", sizeof(unsigned int), MAXVETROCWORDS, 0 ); vetrocVME_IN = dmaPCreate("vmeIN",40240,500,0) ; // vetrocVME_IN = dmaPCreate( "vmeIN", sizeof(unsigned int), 10, 0 ); vetrocVME_OUT = dmaPCreate( "vmeOUT", 0, 0, 0 ); dmaPReInitAll(); dmaPStatsAll(); vmeDmaConfig(2,5,1); /* Optimal DMA configuration for the FADC250 */ // int retValConfig = vmeDmaConfig( 2, 2, 0 ); /* Optimal DMA configuration for the FADC250 */ // cout << "retVal for Config is " << retValConfig << endl; } void setup() { int vetroc_addr, iflag, ii; vetroc_addr = (VETROC_SLOT << 19); /* 0 = software synch-reset, FP input 1, internal clock */ iflag = 0x00; nvetroc = 0; nvetroc = vetrocInit( (VETROC_SLOT << 19), 0x80000, 1, iflag ); if ( nvetroc <= 0 ) { printf( "ERROR: no VETROC. Bye ! \n" ); return; } vetrocGSetProcMode( /*4000*/2000,/*4000*/2000 ); /* Maybe ? pick one of these 2 ? */ /* vetrocEnableMultiBlock(1); */ /* vetrocDisableMultiBlock(); */ /* Construct SlotMask Here you'd want to loop over slots if you had more than 1 slot, using vetrocSlot(index) to find slot numbers */ vetrocSlotMask = 0; vetrocSlotMask |= (1 << VETROC_SLOT); /* Add it to the mask */ printf( "vetrocSlotMask=0x%08x\n", vetrocSlotMask ); vetrocSetBlockLevel( VETROC_SLOT, block_level ); vetrocTriggerPulseWidth( VETROC_SLOT, 8000 ); vetrocLinkReset( VETROC_SLOT ); vetrocClear( VETROC_SLOT ); vetrocPulserSetup( VETROC_SLOT, pulseFrequency, dutyCycle, 0xffffffff ); vetrocSetTrigSource( VETROC_SLOT, VETROC_SD_MUX_PULSER ) ; setupDMA(); return; } void createTrigger() { // First trigger the board // vetrocTrig( VETROC_SLOT ); /* see if there are any triggers */ /* there wont be unless we create them */ int itime, gbready, i; read_stat = 0; for ( itime = 0; itime < 100000; itime++ ) { gbready = vetrocGBready(); read_stat = (gbready == vetrocSlotMask); /* printf("expected mask 0x%08x, got 0x%08x\n",vetrocSlotMask,gbready); */ if ( read_stat > 0 ) { // printf( "expected mask 0x%08x, got 0x%08x\n", vetrocSlotMask, gbready ); break; } } // if ( read_stat != 0 ) printf( "vetroc IS ready !!!\n" ); if ( read_stat == 0 ) printf( "vetroc not ready !!!\n" ); return; } void getData() { unsigned int event_number = 1; GETEVENT( vetrocVME_IN, event_number ); // cout << "DMA event pointer is " << hex << showbase << the_event << dec <part->size << " event length address is " << hex << &(the_event->length) << dec << endl; // cout << "Node size is " << sizeof(DMANODE) << endl; // cout << "DMA buffer is at " << dma_dabufp << endl; PUTEVENT( vetrocVME_OUT ); DMANODE *outEvent = dmaPGetItem(vetrocVME_OUT); len = (outEvent->length); // printf( "VETROC: slot=%d, nw=%d, data-> 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", // VETROC_SLOT, len, LSWAP( tdcbuf[0] ), LSWAP( tdcbuf[1] ), LSWAP( tdcbuf[2] ), // LSWAP( tdcbuf[3] ), LSWAP( tdcbuf[4] ), LSWAP( tdcbuf[5] ), LSWAP( tdcbuf[6] ) ); if ( len != 8460 ) { cout << "The length read from the board is " << len << " words" << endl; } if ( len == 0 ) printf( "VETROC: no data or error. Bye ! \n" ); // if ( len != 8 ) { for ( i = 0; i < len; i++ ) { // cout << "data pointer is " << hex << outEvent->data << " , next node is at " << outEvent->n << // " previous node is at " << outEvent->p << endl; vetrocDataDecode( LSWAP( outEvent->data[i] ) ); } // printf( "\n\n\n\n\n"); // } dmaPFreeItem(outEvent); // usleep(1000); } //unsigned int* dmaBufferAfterTransfer() { // extern DMANODE *the_event; // extern unsigned int *dma_dabufp; // unsigned int event_number = 1234; /* change this to whatever you want */ // GETEVENT(vmeIN,event_number); // //} void vetrocDataDecode( unsigned int data ) { // Routine from B. Moffit for FADC. Here we attempt to adapt for VETROC. // int i_print = 1; static unsigned int type_last = 15; /* initialize to type FILLER WORD */ static unsigned int time_last = 0; static unsigned int iword = 0; // Note, vetroc_data_struct vetroc_data is global, see top of code // if ( i_print ) printf( "%3d: ", iword++ ); if ( data & 0x80000000 ) /* data type defining word */ { vetroc_data.new_type = 1; vetroc_data.type = (data & 0x78000000) >> 27; } else { vetroc_data.new_type = 0; vetroc_data.type = type_last; } switch ( vetroc_data.type ) { case 0: /* BLOCK HEADER */ vetroc_data.slot_id_hd = ((data) & 0x7C00000) >> 22; vetroc_data.n_evts = (data & 0x3FF800) >> 11; vetroc_data.blk_num = (data & 0x7FF); if ( i_print ) printf( "%8X - BLOCK HEADER - slot = %d n_evts = %d n_blk = %d\n", data, vetroc_data.slot_id_hd, vetroc_data.n_evts, vetroc_data.blk_num ); break; case 1: /* BLOCK TRAILER */ vetroc_data.slot_id_tr = (data & 0x7C00000) >> 22; vetroc_data.n_words = (data & 0x3FFFFF); if ( i_print ) printf( "%8X - BLOCK TRAILER - slot = %d n_words = %d\n", data, vetroc_data.slot_id_tr, vetroc_data.n_words ); break; case 2: /* EVENT HEADER */ if ( vetroc_data.new_type ) { vetroc_data.evt_num_1 = (data & 0x7FFFFFF); // if ( 1 ) if ( i_print ) printf( "%08X - EVENT HEADER 1 - evt_num = %d\n", data, vetroc_data.evt_num_1 & 0xFFFFF ); } // else { // vetroc_data.evt_num_2 = (data & 0x7FFFFFF); // if ( 1 ) //// if ( i_print ) // printf( "%8X - EVENT HEADER 2 - evt_num = %d\n", data, vetroc_data.evt_num_2 ); // } break; case 3: /* TRIGGER TIME */ if ( vetroc_data.new_type ) { vetroc_data.time_1 = (data & 0xFFFFFF); if ( i_print ) // if ( 1 ) printf( "%8X - TRIGGER TIME 1 - time = %08x\n", data, vetroc_data.time_1 ); vetroc_data.time_now = 1; time_last = 1; } else { if ( time_last == 1 ) { vetroc_data.time_2 = (data & 0xFFFFFF); if ( i_print ) printf( "%8X - TRIGGER TIME 2 - time = %08x\n", data, vetroc_data.time_2 ); vetroc_data.time_now = 2; } else if ( time_last == 2 ) { vetroc_data.time_3 = (data & 0xFFFFFF); if ( i_print ) printf( "%8X - TRIGGER TIME 3 - time = %08x\n", data, vetroc_data.time_3 ); vetroc_data.time_now = 3; } else if ( time_last == 3 ) { vetroc_data.time_4 = (data & 0xFFFFFF); if ( i_print ) printf( "%8X - TRIGGER TIME 4 - time = %08x\n", data, vetroc_data.time_4 ); vetroc_data.time_now = 4; } else if ( i_print ) printf( "%8X - TRIGGER TIME - (ERROR)\n", data ); time_last = vetroc_data.time_now; } break; case 4: /* nothing yet */ case 5: case 6: case 7: break; case 8: /* PULSE TIME */ vetroc_data.chan = (data & 0x7800000) >> 23; vetroc_data.pulse_num = (data & 0x600000) >> 21; vetroc_data.quality = (data & 0x180000) >> 19; vetroc_data.time = (data & 0xFFFF); if ( i_print ) printf( "%8X - PULSE TIME - chan = %d pulse # = %d quality = %d time = %d\n", data, vetroc_data.chan, vetroc_data.pulse_num, vetroc_data.quality, vetroc_data.time ); break; case 9: /* nothing yet */ case 10: case 11: case 12: break; case 13: /* END OF EVENT */ if ( i_print ) printf( "%8X - END OF EVENT = %d\n", data, vetroc_data.type ); break; case 14: /* DATA NOT VALID (no data available) */ if ( i_print ) printf( "%8X - DATA NOT VALID = %d\n", data, vetroc_data.type ); break; case 15: /* FILLER WORD */ if ( i_print ) printf( "%8X - FILLER WORD = %d\n", data, vetroc_data.type ); break; } type_last = vetroc_data.type; /* save type of current data word */ }