/* Program to test the communications with ADCs */ /* using the readout buffer card and the adclib2000b libraries */ /* Command argument: channel numer (1 to 4) */ /* Not using smem.h because testadc2002.c is in lynxdev.cern.ch */ // For RB VERSION 2 and ADC VERSION 5 /* July 2003 */ #include "adclib03.h" #include "rblib.h" #include #include #include #include #include //#include "ttcvi.h" #define OFF 0 #define ON 1 /*#define BASE 0xDE000000 #define RBUF 0x590000 */ #define RB 0xCD590000 #define REG 0x02 #define TTC 0x300E //#define TTC 0xCD580000 #define GAIN 0x000B #define DAC 50 #define DEL 2 // Gains configurations: // 1 -> 0x000E // 2 -> 0x000D // 3 -> 0x000F // 4 -> 0x000B DEFAULT // 5 -> 0x0007 // 6 -> 0x0003 unsigned char *vrb; void sigbus_handler(); extern struct QuadCANStruct QuadCAN; // Structure to the CAN chips registers for DUMP functions. // First finds out Already initialized ADC cards // by looping cards numbers form 1 to 16 and requesting the // serial number. if it times out, no card is assigned. // If it returns, the cards is added to the table main(int argc, char *argv[]) { int i,j,k, c, di, dx; // loops indexes int status; // status register char s[8]; // String for gets int chn; int dlc2, id2, chn2; // Parameters for Test 11 int counter[12]; // Counter that counts incoming messages for Test 11 double freq; FILE *adclist; // Pointer to the table of available adc cards int nadcs; // Number of ADCs found (1 to 16) int inited[17]; // Flag that indicates presence of a board int id[17]; // Base address for found ADCs char sn[17][8]; // Serial number for ADCs int version[8]; // String to recover version code char serialn[8]; // String to read back the serial number unsigned short rate; // short to read back timer setting unsigned char npmt; // char to read back npmt unsigned char pos, card; // Pmtlist read back chars unsigned short result;// single convert result int n3in1[17]; // Number of 3in1 cards on each ADC int card3in1[17][49]; // Flag that indicates presence of 3in1 card unsigned short bh, bl; // High and Low bytes to build the bit pattern unsigned short pattern; // 3in1 interface bit pattern unsigned char dat[8]; // array to use with setdescr command unsigned int tmp[16]; //******** test int idd, chan, dlc, rtr, ii; unsigned int data[8]; unsigned int d1, d2, d3, d4; int rtr2; unsigned long Base; unsigned int command, Length; unsigned short ped[17][49]; // Array to contain pedestals data // Retrieve the channel to handle chn = atoi(argv[1]); if ( (chn<1) || (chn>4)) { printf("Usage is: testadc [PORT] with PORT = 1 to 4\n"); exit(0); } // Install Bus Error handler signal(SIGBUS, sigbus_handler); /* Bus error handler */ // Clear all flags for (i=0;i<16;i++) inited[i] = OFF; // Start CAN commns using the Readout Buffer Card printf("Starting the canbus on port %d\n", chn); // Initialize TTCVI /* ttcvi_map(TTC); ttcvi_reset(); printf("TTCVI ready.\n"); */ vrb = (unsigned char *) smem_create ("/rbvme", (char *)RB, 0x1000, SM_READ | SM_WRITE); /* vme mapping */ printf("Readout Buffer mapped in VME space.\n"); /* // Reset the ADC card reset_can(TTC, 1); sleep(1); reset_can(TTC,0); sleep(1); printf("GNRST signal sent.\n"); */ /* vrb=(unsigned char *)(BASE+RBUF); */ rb_rstfifos(vrb); /* Reset fifos */ // Reset Microcontroller c=1; rb_rstmicro(vrb, 1); while(rb_rdstat(vrb) != 0xFFB6) { rb_rstmicro(vrb, 1); c++; printf("Reset called %d times\n",c); } /* if ( rb_rdstat(vrb) != 0xFFB6 ) { printf("MICRO RESET:\t\t\t\t\tRDSTAT=%x\n", rb_rdstat(vrb) ); exit(0); } else printf("MICRO RESET:\t\t\t\t\t---ON---\n");*/ printf("MICRO RESET:\t\t\t\t\t---ON---\n"); printf("Wait 1 second...\r"); fflush(stdout); sleep(1); c=1; rb_rstmicro(vrb, 0); while(rb_rdstat(vrb) != 0xFF36) { rb_rstmicro(vrb, 0); c++; printf("Reset called %d times\n",c); } /* rb_rstmicro(vrb, 0); if ( rb_rdstat(vrb) != 0xFF36 ) { printf("MICRO RESET:\t\t\t\t\tRDSTAT=%x\n", rb_rdstat(vrb) ); exit(0); } else printf("MICRO RESET:\t\t\t\t\t ---OFF--\n"); */ printf("MICRO RESET:\t\t\t\t\t ---OFF--\n"); printf("Wait 1 second...\r"); fflush(stdout); sleep(1); /* rb_rstmicro(vrb,1); sleep(1); rb_rstmicro(vrb,0); */ rb_setdumpmode((int)vrb, (char)0x00); // Enable STANDARD mode rb_can_start(vrb, chn, 1, 0x1C, 0x40); /* 250kbps */ // rb_can_start(vrb, chn, 0, 0x1C, 0x40); /* 500kbps */ rb_can_rimr(vrb, chn, 0xFFFF); // All 16 buffers can receive messages rb_enable(vrb, 0x01 << (chn-1) ); // On specified CAN port cause interrupts // Canbus is now running // read the ADC Cards List // The list of adc cards connected is specified in file adclist.txt // The list format is [Base address] [Serial number] // with base address = 1 to 16. // With serial number = text stamped on the card status = 0; i = 1; adclist = fopen("adclist.txt", "r"); if ((int)adclist != -1) while(status != EOF) { status = fscanf(adclist, "%d %s\n", &id[i], &sn[i]); i++; } nadcs = i-2; printf("i=%d, nadcs=%d nadcs=%d\n",i,nadcs,nadcs); fclose(adclist); // Now base address of card i is in id[i] // Now serial number of card i is in sn[i] // Reset all ADC cards // If cards were already initialized in the past, this will put them back // in the id_allocated state. // If the cards are doing a cold startup, nothing will happen // This will put the cards in a known state. printf("put nadcs: %d\n",nadcs); // RESTART all the cards to go back in a not idallocated state for(i=1;i<=16;i++) adc_restart((int)vrb, chn, i<<6); sleep(1); // Allocate identifiers // If the identifier was already allocated, it will time out // If the identifiers are not allocated yet it is done here for (i=1;i<=nadcs;i++) { // Prepare register to receive acks of id_alloc command rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // 1st ack in reg 1 // The identifier allocation is as follows // an id_alloc command is broadcasted with ID=0 on the CAN bus // the adc card that receive the id_alloc command compares the sn with its onw sn. // if the serial number sn matches, then it will start to use the base identifier i<<6 // then it sends back its serial number and code version status = adc_idalloc((int)vrb, chn, sn[i], id[i]); printf("Status = %d\n", status); if (status == 0) printf("NEW ID ALLOCATION ON CARD %s WITH ID %d\n", sn[i], id[i]); } // Init all ADC cards to enter the DAQ state for (i=1;i<=nadcs;i++) { printf("id[%02d] = %d, %x\n", i, id[i], id[i]<<6); // Prepare to receive the acks of init command, note that 2 acks are sent back! rb_can_mask(vrb, chn, 1, (id[i]<<6)+1); // 1st ack in reg 1 rb_can_mask(vrb, chn, 2, (id[i]<<6)+2); // 2nd ack in reg 2 status = adc_init((int)vrb, chn, id[i]<<6, GO_FB, version); // GO_FB to enter the DAQ state printf(" adc init \n"); if (status == 0) inited[i] = ON; // cards initzed successfully will have their inited flag ON else inited[i] = OFF; // cards that could not be initzed will have the inited flag OFF } // Report the initialization result for (i=1;i<=nadcs;i++) { if (inited[i]==ON) printf("Found %s with Id %d\n", sn[i], id[i]); else printf("Missing %s with Id %d\n", sn[i], id[i]); } // Test the initialized adc cards (those with their inited flag ON for (i=1;i<=nadcs;i++) { if (inited[i]==ON) { printf("TESTING ADC %s:\n", sn[i]); printf("------------------\n"); // Test 1: read the serial number of the card rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // reply is in reg 14 status = adc_get_serialnumber((int)vrb, chn, id[i]<<6, serialn); if (status == 0) printf("Serial number is %s\n", serialn); if (status == 1) { printf("Serial number is incorrect!\n"); while(status==1) { status=adc_get_serialnumber((int)vrb, chn, id[i]<<6, serialn); } } if (status == -1) printf("Serial number could not be tead back.\n"); // Test 2: test TIMER settings 0x5555 and 0xAAAA // Prepare mask to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Set the timer, read it back, compare, for values 0xaaaa and 0x5555 status = adc_rate((int)vrb, chn, (id[i]<<6), 0xAAAA); if (status == 0) { status = adc_get_rate((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0)&&(rate==0xAAAA) ) { printf("TIMER SET SUCCESFULLY TO 0xAAAA\n"); status = adc_rate((int)vrb, chn, (id[i]<<6), 0x5555); if (status == 0) { status = adc_get_rate((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0) && ((int)rate == 0x5555) ) { printf("TIMER SET SUCCESSFULLY TO 0x5555\n"); } else printf("TIMER NOT SET SUCCESSFULLY TO 0x5555\n"); } else printf("COULD NOT SEND ADC_RATE COMMAND\n"); } else printf("TIMER NOT SET SUCCESSFULLY TO 0xAAAA\n"); } else printf("COULD NOT SEND ADC_RATE COMMAND\n"); // Test 3: test NPMT settings from 1 to 48 // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Set NPMT, read it back, compare, for values 1 to 48 for (j=1;j<=48;j++) { status = adc_npmt((int)vrb, chn, (id[i]<<6), (char)j); if (status == 0) { status = adc_get_npmt((int)vrb, chn, (id[i]<<6), &npmt); if ( (status == 0)&&(npmt==(unsigned char)j) ) { printf("NPMT SET SUCCESFULLY TO %d\r", j); } else printf("NPMT NOT SET SUCCESSFULLY TO %d, READ %d, status=%d\n", j, npmt, status); } else printf("COULD NOT SEND ADC_NPMT COMMAND\n"); } printf("\n"); // Test 4: test MAXSCAN settings 0xAAAA and 0x5555 // Prepare mask to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Set maxscan, read it back, compare, for values 0xaaaa and 0x5555 status = adc_maxscans((int)vrb, chn, (id[i]<<6), 0xAAAA); if (status == 0) { status = adc_get_maxscans((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0)&&(rate==0xAAAA) ) { printf("MAXSCANS SET SUCCESFULLY TO 0xAAAA\n"); status = adc_maxscans((int)vrb, chn, (id[i]<<6), 0x5555); if (status == 0) { status = adc_get_maxscans((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0) && ((int)rate == 0x5555) ) { printf("MAXSCANS SET SUCCESSFULLY TO 0x5555\n"); } else printf("MAXSCANS NOT SET SUCCESSFULLY TO 0x5555\n"); } else printf("COULD NOT SEND ADC_MAXSCANS COMMAND\n"); } else printf("MAXSCANS NOT SET SUCCESSFULLY TO 0xAAAA\n"); } else printf("COULD NOT SEND ADC_MAXSCANS COMMAND\n"); // Test 5: test DACSET settings from values 0 to 255 // Note that this cannot be read back, use scope to check // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception // Set DACSET, read it back, compare, for values 1 to 48 for (j=0;j<=255;j++) { status = adc_dacset((int)vrb, chn, (id[i]<<6), (char)j); if (status == 0) { printf("DACSET SET SUCCESFULLY TO %d\r", j); adc_dacset((int)vrb, chn, (id[i]<<6), 50); // Put back a default value } else printf("DACSET NOT SET SUCCESSFULLY TO %d, status=%d\n",j, status); } printf("\n"); // Test 6: test DELAY seetings for values 0xaaaa and 0x5555 // Prepare mask to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Set delay, read it back, compare, for values 0xaaaa and 0x5555 status = adc_delay((int)vrb, chn, (id[i]<<6), 0xAAAA); if (status == 0) { status = adc_get_delay((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0)&&(rate==0xAAAA) ) { printf("DELAY SET SUCCESFULLY TO 0xAAAA\n"); status = adc_delay((int)vrb, chn, (id[i]<<6), 0x5555); if (status == 0) { status = adc_get_delay((int)vrb, chn, (id[i]<<6), &rate); if ( (status == 0) && ((int)rate == 0x5555) ) { printf("DELAY SET SUCCESSFULLY TO 0x5555\n"); adc_delay((int)vrb, chn, id[i]<<6, 3); // Put again a small value } else printf("DELAY NOT SET SUCCESSFULLY TO 0x5555\n"); } else printf("COULD NOT SEND ADC_DELAY COMMAND\n"); } else printf("DELAY NOT SET SUCCESSFULLY TO 0xAAAA\n"); } else printf("COULD NOT SEND ADC_DELAY COMMAND\n"); // Test 7: fill the pmtlist and check the contents // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Set PMTLIST, read it back, compare, for positions 0 to 47 for (j=0;j<=47;j++) { status = adc_pmtlist((int)vrb, chn, (id[i]<<6), (char)j, (char)(j*2)); if (status == 0) { status = adc_get_pmtlist((int)vrb, chn, (id[i]<<6), j, &card); if ( (status == 0)&&(card==(unsigned char)(j*2) ) ) { printf("PMTLIST SET SUCCESFULLY FOR POS %d\r", j); } else printf("PMTLIST NOT SET SUCCESSFULLY FOR POS %d, READ %d, status=%d\n",j, card, status); } else printf("COULD NOT SEND ADC_PMTLIST COMMAND\n"); } printf("\n"); // Test 8: send a 3in1 pattern = 0xaa55; // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception // Set 3in1SET, no readback, no compare, for value 0xaa55 status = adc_3in1set((int)vrb, chn, (id[i]<<6), 0xaa55); if (status == 0) { printf("3in1SET SENT SUCCESFULLY\n"); } else printf("3in1SET NOT SENT SUCCESSFULLY, status=%d\n", status); // Test 9 : get 3in1 and display // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Call 3in1GET, no readback, no compare status = adc_3in1get((int)vrb, chn, (id[i]<<6), &rate); if (status == 0) { printf("3in1GET SENT SUCCESFULLY, RETURNED %4x\n", rate); } else printf("3in1GET NOT SENT SUCCESSFULLY, status=%d\n", status); // Test 10: Single Convert // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result // Call CONVERT, display result, use card 1 status = adc_3in1set((int)vrb, chn, (id[i]<<6), (0xC4 << 8) + 1); // CARDSELECT // status = adc_convert((int)vrb, chn, (id[i]<<6), 1, &result); adc_delay((int)vrb, chn, id[i]<<6, 1); // Put again a small value // status = adc_convert((int)vrb, chn, (id[i]<<6), &result); data[0] = CONVERT; // can_tx((int)vrb, chn, (id[i]<<6)+1, 1, 0, data); // rb_can_send((int)vrb, chn, (id[i]<<6)+1, 1, data); tmp[0] = (( (id[i]<<6)+1 ) >> 8) & 0x00000007; tmp[1] = ( (id[i]<<6)+1 ) & 0x000000FF; tmp[2] = 1; tmp[3] = CONVERT; Base=(int)vrb; rb_wrcmd(Base, SEND, chn, 4, tmp); rb_can_recv((int)vrb, &chn2, &id2, &dlc2, tmp); if (status == 0) { printf("CONVERT SENT SUCCESFULLY, RETURNED %d\n", result); } else printf("CONVERT NOT SENT SUCCESSFULLY, status=%d\n", status); // Test 10B: CONVERT Function in fastdump mode rb_setdumpmode((int)vrb, (char)0x01); // Enable DUMP mode // Prepare masks to receive answers rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 14, (id[i]<<6)+14); // REQUEST result rb_can_rimr(vrb, chn, 0x4000); // Only new message in buffer 14 will generate an interrupt // 0001 0002 0004 0008 -> buffers 0,1,2,3 ... next 4 in the next slot rb_enable(vrb, 0x01 << (chn-1) ); // On specified CAN port cause interrupts // Call DM_CONVERT status = adc_dm_convert((int)vrb, chn, (id[i]<<6)); status=rb_getfastdump((int)vrb, &QuadCAN); if (status == RB_SUCCESS) { printf("------------------------------------------------- FAST DUMP RECORD ---------------------------------------------|\n"); printf("----------------------------------------------------------------------------------------------------------------|\n"); printf("-------|--------- CAN0 ----------|--------- CAN1 ---------|---------- CAN2 ---------|----------- CAN3 ----------|\n"); printf("RRR1 | 0x%2x | 0x%2x | 0x%2x | 0x%2x |\n", QuadCAN.CAN[0].RRR1,QuadCAN.CAN[1].RRR1,QuadCAN.CAN[2].RRR1,QuadCAN.CAN[3].RRR1); printf("RRR2 | 0x%2x | 0x%2x | 0x%2x | 0x%2x |\n", QuadCAN.CAN[0].RRR2,QuadCAN.CAN[1].RRR2,QuadCAN.CAN[2].RRR2,QuadCAN.CAN[3].RRR2); printf("----------------------------------------------------------------------------------------------------------------|\n"); for(ii=0;ii<16;ii++) { printf("DSCR%2d | 0x%4x | 0x%4x | 0x%4x | 0x%4x |\n",ii, (QuadCAN.CAN[0].DESCRIPTOR[ii])>>5, (QuadCAN.CAN[1].DESCRIPTOR[ii])>>5, (QuadCAN.CAN[2].DESCRIPTOR[ii])>>5, (QuadCAN.CAN[3].DESCRIPTOR[ii])>>5); } printf("----------------------------------------------------------------------------------------------------------------|\n"); for (ii=0;ii<16;ii++) { printf("MSG%2d | ",ii); for (j=0;j<4;j++) { for(k=0;k<8;k++) printf("%2x ", QuadCAN.CAN[j].Msg[ii].Byte[k]); printf(" |"); } printf("\n"); } } else { printf("FAST DUMP Failed.\n"); exit(0); } rb_setdumpmode((int)vrb, (char)0x00); // Enable STANDARD mode, Disable DUMP Mode // Test 11: test the automatic scans using the RBUF periodic triggers. // Prepare masks to receive answers printf("id i = %d\n", id[i]); rb_can_mask(vrb, chn, 1, (id[i]<<6) ); // ACK reception rb_can_mask(vrb, chn, 2, (id[i]<<6)+2); // result rb_can_mask(vrb, chn, 3, (id[i]<<6)+3); // result rb_can_mask(vrb, chn, 4, (id[i]<<6)+4); // result rb_can_mask(vrb, chn, 5, (id[i]<<6)+5); // result rb_can_mask(vrb, chn, 6, (id[i]<<6)+6); // result rb_can_mask(vrb, chn, 7, (id[i]<<6)+7); // result rb_can_mask(vrb, chn, 8, (id[i]<<6)+8); // result rb_can_mask(vrb, chn, 9, (id[i]<<6)+9); // result rb_can_mask(vrb, chn, 10, (id[i]<<6)+10); // result rb_can_mask(vrb, chn, 11, (id[i]<<6)+11); // result rb_can_mask(vrb, chn, 12, (id[i]<<6)+12); // result rb_can_mask(vrb, chn, 13, (id[i]<<6)+13); // result printf("rdstat=%x\n", rb_rdstat((int)vrb)); // Messages will arrive into buffers 2 to 13, and interrupt is triggered on reception of the last message in buffer 13 only // ACKS are received in buffer 1 and must be enabled for interrupt generation as well rb_can_rimr(vrb, chn, 0x2002); // Only new message in buffer 13 will generate an interrupt // number of pmts adc_npmt((int)vrb, chn, id[i]<<6, 48); printf("set npmt...\n"); printf("rdstat=%x\n", rb_rdstat((int)vrb)); // maxscans adc_maxscans((int)vrb, chn, id[i]<<6, 150); printf("set maxscan...\n"); printf("rdstat=%x\n", rb_rdstat((int)vrb)); // Configure the rbuf periodic trigger in can buffer 15 tmp[0]=TRIGGER; rb_can_setdescr((int)vrb, chn, 15, (id[i]<<6)+1, 1, tmp); printf("set trigger message...\n"); usleep(1000); printf("rdstat=%x\n", rb_rdstat((int)vrb)); // Configure the trigger rate rb_can_periodic((int)vrb, 0x01 << (chn-1)); // Enable periodic tx for channel 1 usleep(1000); printf("rdstat=%x\n", rb_rdstat((int)vrb)); printf("wait 1/2 second...\n"); fflush(stdout); rb_can_timed((int)vrb, 0xC620); // Configure the timer for 100Hz at CBE9, 66Hz with C620 usleep (500000); rb_can_notimer((int)vrb); // stop the timer printf("timer stopped...\n"); // Reset the message counter for (j=0;j<12;j++) counter[j]=0; // Retrieve the data j=0; while(rb_rdstat(vrb)!=0xFF36) { rb_can_recv(vrb, &chn2, &id2, &dlc2, dat); printf ("Received message %4d\r", j); counter[ (id2&0x000F)-2 ]++; j++; } freq = 2*((double)j)/(12.0); printf("TIMED:\t\t\t\t\t ---OK---\tRATE=%3.2f Hz\n", freq); for (j=0;j<12;j++) printf("Number of messages with offset %4x = %4d\n", j+2 ,counter[j]); } } smem_create("/rbvme", (unsigned char *)vrb, 0x1000, SM_DETACH); smem_remove("/rbvme"); } void sigbus_handler() { // printf("BUS ERROR\n"); // smem_create("/rbvme", (unsigned char *)vrb, 0x1000, SM_DETACH); // smem_remove("/rbvme"); // printf("Exiting...\n"); exit(2); }