Skip to content
Snippets Groups Projects
pcie40_ul_lib.cpp 10.85 KiB
#include "pcie40_ul_lib.h"

int crc_calc( int * crc, unsigned int * data ){ 
  int byte1, byte2, byte3, byte4 ;
  byte1 = (*data) & 0xFF;
  byte2 = ( (*data) & 0xFF00 ) >> 8;
  byte3 = ( (*data) & 0xFF0000 ) >> 16;
  byte4 = ( (*data) & 0xFF000000 ) >> 24;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte4] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte3] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte2] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte1] ;
}


int crc_calc_event( unsigned int* data, int start_pos ){
  int i = 0;
  int cur_pos = start_pos;
  int first_crc ;
  int crc = 0xffff ;
  int size = data[ cur_pos % DMASIZE ];

  int good_flag = 0;

  if( size > 0xffff || size <= 0 ){
    printf("Invalid total event size %.8x\n", size);
    return -1;
  }

  /* printf( "TRL %.8x %.8x %.8x\n",  */
  /* 	  data[ ( cur_pos + size - 1 + DMASIZE ) % DMASIZE ],  */
  /* 	  data[ ( cur_pos + 1 + size ) % DMASIZE ],  */
  /* 	  data[ ( cur_pos + 2 + size ) % DMASIZE ] );  */

  cur_pos = start_pos + 4;
  unsigned int ctime = data[ cur_pos % DMASIZE ];

  cur_pos = start_pos + 3;
  unsigned int evenum = data[ cur_pos % DMASIZE ];
  cur_pos = start_pos + 5;
  unsigned int utime = data[ cur_pos % DMASIZE ];
  cur_pos = start_pos + 2;
  unsigned int exp_run = data[ cur_pos % DMASIZE ] ;

  int offset = 8; // size of ROB header [words]

  int link_num = 0;


  crc_calc( &crc, &ctime );
  crc_calc( &crc, &evenum );
  crc_calc( &crc, &utime );
  crc_calc( &crc, &exp_run );
  first_crc = crc ;

  
#ifdef DEBUG
  printf("Start\n");
  for( i = start_pos ; i < start_pos + size ; i++){
    printf("%.8x\n", data[ i % DMASIZE ] );
  }
  printf("End\n");
#endif
  int bad = 0;
  
  while( offset + 4 < size ){ // 4 = ROB trailer size
    cur_pos = start_pos + offset;
    int size_link = data[ cur_pos % DMASIZE ] & 0x000ffff ;
    if ( 0 >= size_link || size_link > 10000000 ){
      printf("[ERROR] Invalid size per link (%.8x words): link num %d\n", size_link, link_num);
      return -1 ; // it could be that the memory was read
    } 

    //
    // Calculation of CRC
    //
    crc = first_crc ;
#ifdef DEBUG
    printf("%.8x %.8x crc %.8x\n", data[ ( start_pos + offset ) % DMASIZE ], data[ ( start_pos + offset + 1 ) % DMASIZE ], crc );
#endif
    for ( cur_pos = start_pos + offset + 2 ; cur_pos < start_pos + offset + size_link -2; ++cur_pos ) {
      crc_calc( &crc, &data[ cur_pos % DMASIZE ] );
#ifdef DEBUG
      printf("crc %.8x data %.8x\n", crc, data[ cur_pos % DMASIZE ] );
#endif
    }
#ifdef DEBUG
    printf("%.8x %.8x\n", data[ ( cur_pos ) % DMASIZE ], data[ ( cur_pos + 1 ) % DMASIZE ]);
#endif
    //    cur_pos = start_pos +  8 + size_link -2;
    cur_pos = start_pos + offset + size_link -2;
#ifdef DEBUG
    printf("calcd %.4x data %.4x\n", crc, data[ cur_pos % DMASIZE ] & 0xffff );
#endif

    //
    // Check of CRC
    //
    if( ( crc & 0xffff ) != ( data[ cur_pos % DMASIZE ] & 0xffff ) ){
      printf("%.2d Bad  ! calcd %.4x data %.4x offset %.4x size %.4x szlnk %.4x trl %.8x\n", 
	     link_num, crc, data[ cur_pos % DMASIZE ] & 0xffff, offset, size, size_link, data[ (cur_pos+1) % DMASIZE ] );
      bad = 1;

    }else{
      good_flag = 1;
       // printf("%.2d Good ! calcd %.4x data %.4x offset %.4x size %.4x szlnk %.4x trl %.8x\n",  
       // 	      link_num, crc, data[ cur_pos % DMASIZE ] & 0xffff, offset, size, size_link, data[ (cur_pos+1) % DMASIZE ] ); 

    }
    link_num++;
    offset += size_link;
  }

  if( bad ){
  //  if( evenum > 50000 ){
    //  if( 1 ){
    for( i = 0 ; i < size ; i++){
      printf("%.8x ", data[ ( start_pos  + i ) % DMASIZE ] );
      if( i % 8 == 7 ) printf("\n");
    }
    printf("\n");
    good_flag = -2;
  }
  return good_flag;
     
}

  int decode_data_wUL( unsigned int * data , unsigned int * ce , int * crc , int * run , 
		       int * bad , int *evn , int * retry , int * pctime , int * putime , 
		       int * nmissed ) { 

    int magic; 
    int size, size_link;
    int ix ;

    int offset; 
    unsigned int exp_run, evenum, ctime, utime; 
    int start_pos = *ce;
    int cnt = 0;
    int cur_pos = *ce + 1;
    int ret = 0;
    
    while( !( ( ( magic = data[ cur_pos % DMASIZE ] ) & 0xffff0000 ) != 0x7f7f0000 ) ){
      usleep(1000);
      cnt++;
      //
      // Scan to find x"7f7f...."
      //
      if( cnt > 10 ){
	cnt = 0;
	int j = 0 ; 
	for ( j = 0 ; j < DMASIZE ; ++j ) { 
	  if ( ( ( data[ ( cur_pos + j ) % DMASIZE ] & 0xffff0000 ) == 0x7f7f0000 ) ){
	    evenum = data[ ( cur_pos + j + 2 ) % DMASIZE ];
	    if( evenum > *evn ){
	      *evn = evenum;
	      cur_pos = ( cur_pos + j - 1 + DMASIZE ) % DMASIZE;
	      size = data[ cur_pos ] ;
	      *ce = ( cur_pos + size ) % DMASIZE;
	      printf( "New Event number prev %d new %d pos %d size %d\n" , *evn ,  evenum, cur_pos, size );
	      crc_calc_event( data, cur_pos );

	    }else{
	      printf( "Old Event number prev %d new %d pos %d\n" , *evn ,  evenum, ( cur_pos + j - 1 + DMASIZE ) % DMASIZE );
	      break;
	    }
	  }else{
	    continue;
	  }
	}
      }
    }

    return size ;
  }

int readout(){
//  int main (int argc ,char** argv) {
    // Stop trigger
    /* system( "ssh robbep@vme \"resetft -53\"" ) ; */
    /* sleep( 2 ) ;  */

    int res = ecs_open( 0 , 0 ) ;
    if ( -1 == res ) printf("ERROR: Could not open device (BAR 0)\n") ;
    else printf("SUCCESS: Device opened for DMA\n");
    res = ecs_open( 0 , 2 ) ;
    // ecs_write( 0 , 2 ,  0x000501A0 , 0x0 ) ;
    ecs_write( 0 , 2 ,  0x000501A0 , 0x1 ) ;
    pcie40_b2dmabufferreset( 0 ) ; 
    // Start trigger
    //  fp = popen( "ssh robbep@vme \"trigft -53 pulse 1000 -1\"" , "r" ) ;
    // sleep( 2 ) ;
    /* while( fgets( buf , sizeof(buf) , fp ) != NULL ) {  */
    /*   // printf( "A= %d\n" , strncmp( exp , buf , 3 ) ) ; */
    /*   //    printf( strncmp( &buf[0] , 'exp' , 1 ) ) ; */
    /*   tmp = strdup( buf ) ; */
    /*   if ( strncmp( exp , buf , 3 ) == 0 ) { */
    /*     //printf( '%s\n' , buf )  ; */
    /*     // printf( "ICI\n" ) ; */
    /*     ptr = strtok( tmp , " " ) ; */
    /*     ptr = strtok( NULL , " " ) ; */
    /*     ptr = strtok( NULL , " " ) ; */
    /*     ptr = strtok( NULL , " " ) ; */
    /*     // while ( ptr != NULL ) { */
    /*     run = atoi( ptr ) ;  */
    /*     //	ptr = strtok( NULL , " " ) ;  */
    /*   } */
    /*     //} */
    /* } */
    /* pclose( fp ) ; */
    //sleep( 2 ) ; 

    int run  = 0 ; 
    FILE* fp; 
    char * ptr ;
    char * tmp ;
    char buf[1000] ;
    char exp[] = "exp" ; 

    unsigned int * data ; 
    double time_spent ;
    int retry ;
    int bad ;
    int evn ;
    evn = 0  ;
    bad = 0 ;
    retry = 0 ;
    int pctime, putime ; 
    pctime = 0 ;
    putime = 0 ;

    int i ;
    int size, size_256, currentEventIndex, crc, nErr, nEvt, nRetry, nMissed ;
    currentEventIndex = 0 ;
    nErr = 0 ;
    nEvt = 0 ;
    nRetry = 0 ;
    nMissed = 0 ;
    int read_dma = 1 ; 
    clock_t begin = clock() ;
    int size_zero_cnt = 0;

    int start_flag = 1;

    int magic; 
    int size_link;

    int offset; 
    unsigned int next_exp_run, cur_exp_run = 0, evenum, ctime, utime, first_eve = 0; 
    int start_pos = 0;
    int cnt = 0;
    int eve_cnt = 0, first_event_flag = 0, crc_err_eve_cnt = 0;
    
    
    int cur_pos = 0;
    int ret = 0;
    unsigned int cur_eve = 0, next_eve = 0;
    int mod_pos = 0;

    //    if ( ( nEvt % 1000 == 1 ) && ( size != 0 ) ) printf( "Event number %d\n", nEvt ) ;

    //
    // Read the 1st data
    //
    if ( read_dma == 1 ) { 
      // set busy
      //res = ecs_write( 0 , 2 ,  0x000501A0 , 0x1 ) ;
      //sleep(5);
      res = pcie40_b2dmapointerread( 0 , &data ) ;
      if ( start_flag == 1 ){
	ecs_write( 0 , 2 ,  0x000501A0 , 0x0 ) ;
	start_flag = 0;
      }
      //usleep( 5 ) ;
      // release busy
      //res = ecs_write( 0 , 2 ,  0x000501A0 , 0x0 ) ;
      read_dma = 1 ;
    } 

    //
    // Main loop
    //
    while( 1 ){
      while( 1 ){
	if( !( ( ( ( magic = data[ ( cur_pos + 1 ) % DMASIZE ] ) & 0xffff0000 ) != 0x7f7f0000 )
	    || data[ ( cur_pos +  data[ cur_pos  % DMASIZE ] - 1 + DMASIZE ) % DMASIZE ] != 0x7fff0006 ) ){
	  break;
	}
	//	printf("MAGIC %.8x\n", magic);

	//	usleep(1000); // to avoid BUSY loop
	
	//
	// Refresh DMA memory
	//
	res = pcie40_b2dmapointerread( 0 , &data ) ;
	int wait_flag = 0;
	//
	// Scan to find x"7f7f...."
	//
	if( cnt > 100 ){
	  cnt = 0;
	  int j = 0 ; 
	  for ( j = 0 ; j < DMASIZE ; ++j ) { 
#ifdef DEBUG	    
	    printf("%.8x %d\n", data[ ( cur_pos + j + 1 ) % DMASIZE ], cur_pos + j );
#endif
	    if ( ( ( data[ ( cur_pos + j + 1 ) % DMASIZE ] & 0xffff0000 ) == 0x7f7f0000 ) ){
	      next_eve = data[ ( cur_pos + j + 3 ) % DMASIZE ];
	      next_exp_run =  data[ ( cur_pos + j + 2 ) % DMASIZE ] ;

	      //	      printf( "TRAILER %.8x %.8x %.8x\n",data[ ( cur_pos + j + data[ ( cur_pos + j + DMASIZE ) % DMASIZE ] - 1 + DMASIZE ) % DMASIZE ] );

	      if( next_eve > cur_eve && next_exp_run >= cur_exp_run ){
		/* if( data[ ( ( data[ ( cur_pos + j + DMASIZE ) % DMASIZE ] ) - 1 + DMASIZE ) % DMASIZE ] != 0x7fff0006 ){ */
		/*   usleep(1000); */
		/*   break; */
		/* } */
		cur_pos = ( cur_pos + j + DMASIZE ) % DMASIZE;
		size = data[ cur_pos ];
		//		printf( "Detect new Event number prev %.8x new %.8x pos %.8x size %.8x\n" , cur_eve , next_eve, cur_pos, size );
		break;
	      }else{
		//		printf( "Detect Old Event number prev %.8x new %.8x pos %d\n" , cur_eve , next_eve, ( cur_pos + j + DMASIZE ) % DMASIZE );
		break;
	      }
	    }else{
	      continue;
	    }
	  }
	}
	cnt++;
      }
      size = data[ cur_pos ] ;
 
      next_eve = data[ ( cur_pos + 3 ) % DMASIZE ];
      next_exp_run = data[ ( cur_pos + 2 ) % DMASIZE ];

      if( first_event_flag == 0 || cur_exp_run != next_exp_run ){
	first_event_flag = 1;
	first_eve = next_eve;
	crc_err_eve_cnt = 0;
	eve_cnt = 0;
      }
      eve_cnt++;
      ret = crc_calc_event( data, cur_pos );
      if( ret != 1 ){
	crc_err_eve_cnt++;
      }
      if(ret != 1 || eve_cnt % 100 == 0 ){
	printf( "Event number prev %.8x new %.8x pos %.8x size %.8x\n" , cur_eve , next_eve, cur_pos, size );
      }
      cur_eve = next_eve;
      cur_exp_run = next_exp_run;
      if(ret != 1 ||  eve_cnt % 10000 == 0 ){
	printf("STATUS : tot eve %d read eve %d err_eve %d run %d\n", next_eve - first_eve, eve_cnt, crc_err_eve_cnt, cur_exp_run );
      }
      mod_pos = ( cur_pos + size ) % 8;
      if( mod_pos != 0 ){
	cur_pos = ( cur_pos + size + DMASIZE + ( 8 - mod_pos) ) % DMASIZE ;
      }else{
	cur_pos = ( cur_pos + size + DMASIZE ) % DMASIZE ;
      }

    }


    clock_t end = clock();
    time_spent += (double)(end - begin) / CLOCKS_PER_SEC;

    ecs_close( 0 , 0 ) ;

    printf( "Timing = %f s\n" , time_spent ) ;
    printf( "Number of events = %d \n", nEvt ) ;  
    printf( "Number of errors = %d \n", nErr ) ; 
    printf( "Number of retries = %d \n", nRetry ) ;
    printf( "Number of missed = %d \n", nMissed ) ;
    return 0 ;
  }