/* program to read data for the source test 
J. Rohlf, August 31, 2001

Identifies blocks by finding a pattern of word_0 with upper 3 bytes zero
followed by word_1 whose lower byte = word_0.
In addition, word_(BLOCKSIZE-1) must have its upper byte = word_0 and 
lower two bytes = BLOCKSIZE.

A summary of link errors is printed.

*/


#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define BLOCKSIZE 0xFB /* data block size, 32 bit words*/
#define PACKAGE_MODE
#define SOURCE_MODE


main()
{

  FILE *fp;
  int rc;
  int i, j, k;
  int unsigned data[BLOCKSIZE];
  int unsigned icount;
  int new_block_flag;
  int block_short;
  int block_long;
  int word_count;
  int word_count_save;
  int block_test;
  int link_error_word;
  int link_error_sum[8];
  int print;
  int num_full_blocks;
  int flag;
  int count;
  int prev_word;
  int actual;
  int block_length_save;
  int good_blocks;
  int bit_test;
  int run_no;
  int word_32;
  int data_read;
  char ic[100];
  int word_16_1;
  int word_16_2;
  int word_1_a;
  int word_1_b;
  int word_2_a;
  int word_2_b;
  int chan_a_sum[32];
  int chan_b_sum[32];
  int cap_id_sum[4];
  int cap_id;
  int glink_err_sum[4];
  int glink_err;
  float ave_a;
  float ave_b;
  float total;
  int c;

  //zero summary
  for(i = 0; i < 32; i++) {
    chan_a_sum[i] = 0;
    chan_b_sum[i] = 0;
    if(i < 4) cap_id_sum[i] = 0;
    if(i < 4) glink_err_sum[i] = 0;
  }

// first run through data and find block length (s)
  fp = fopen( "dump.dat", "r");

#ifdef PACKAGE_MODE
  // read the header block length
  rc = fread(data, 4, 1, fp);

/* read run number and word count (32 bit words) */
  rc = fread(data, 4, 1, fp);
  run_no = data[0];
  rc = fread(data, 4, 1, fp);
  word_32 = data[0];
  printf("run number = %d\n", run_no);
  printf("word count = %d\n", word_32);
#endif

  count = -1;
  prev_word = 0;
  word_count_save = 0xFB;
  actual = 0;
  print = 0;
  block_length_save = 0;
  good_blocks = 0;
  for(k = 0; k < 8; k++) link_error_sum[k] = 0;

  data_read = 0;
  while(1){
    if(data_read >= word_32) break;
    rc = fread(data, 4, 1, fp);
    data_read++;
    if(rc != 1) break;

    if( (data[0] >> 8) == 0) {
      block_short = data[0] & 0xFF;
      rc = fread(data, 4, 1, fp);
      data_read++;
      if(rc != 1) break;

      if( (data[0] & 0xFF) == block_short){
	actual = 0;

	j = 0;
	for(i = 0; i < BLOCKSIZE-2; i++){
	  rc = fread(data, 4, 1, fp);
	  data_read++;
	  if(rc != 1) break;
	  j++;
	  data[j] = data[0];
	  actual++;

	  if( ((data[0] >> 24) == block_short) 
	      && ((data[0] & 0xFFFF) == BLOCKSIZE)){
	    //found end of block
	    i = 1000;
	    if ((actual+2) == BLOCKSIZE) {
	      good_blocks++;
	      link_error_word = (data[0] >> 16) & (0xFF);

	      for(k = 0; k < 8; k++) {
		bit_test = ((data[0] >> 16) & (1 << k));
		if(bit_test != 0) link_error_sum[k] =  link_error_sum[k] + 1;
	      }

	      if(print < 5) {
		printf("Found block no. (byte-0) = 0x %x\n", block_short);
		printf(" first data words   = 0x %x %x %x %x\n", 
		  data[1], data[2], data[3], data[4]);
		printf("                    = 0x %x %x %x %x\n", 
		  data[5], data[6], data[7], data[8]);
		printf("link error byte = 0x %x\n\n", link_error_word);
		print++;
	      }


#ifdef SOURCE_MODE
	      for(k = 1; k < BLOCKSIZE-2; k++){ 
	      word_16_1 = data[k] & 0xffff;
	      word_16_2 = data[k] >> 16;
	      word_1_a = word_16_1 & 31;
	      word_1_b = (word_16_1 >> 7) & 31;
	      word_2_a = word_16_2 & 31;
	      word_2_b = (word_16_2>> 7) & 31;
	      chan_a_sum[word_1_a] = chan_a_sum[word_1_a]++;
	      chan_a_sum[word_2_a] = chan_a_sum[word_2_a]++;
	      chan_b_sum[word_1_b] = chan_b_sum[word_1_b]++;
	      chan_b_sum[word_2_b] = chan_b_sum[word_2_b]++;
	      cap_id = word_16_1 >> 14;
	      cap_id_sum[cap_id]++; 
	      cap_id = word_16_2 >> 14;
	      cap_id_sum[cap_id]++; 
	      glink_err = (word_16_1 >> 12) & 3;
	      glink_err_sum[glink_err]++; 
	      glink_err = (word_16_2 >> 12) & 3;
	      glink_err_sum[glink_err]++; 
	      }
#endif
	    }
	  }

	}

      }


      }

#ifdef PACKAGE_MODE
    //check for end of pay load
    if(data_read == word_32) {
      break;
  }


#endif

  }

    printf("No. of good blocks  = 0x %x\n", good_blocks);
    printf("link error summary (bits 7-0) = 0x %x %x %x %x %x %x %x %x\n", 
		  link_error_sum[7], link_error_sum[6],
		  link_error_sum[5], link_error_sum[4],
		  link_error_sum[3], link_error_sum[2],
		  link_error_sum[1], link_error_sum[0]);

#ifdef SOURCE_MODE
    ave_a = 0;
    ave_b = 0;
    total = 0;
    for(i = 0; i < 32; i++){
      ave_a =  ave_a + i*chan_a_sum[i];
      ave_b =  ave_b + i*chan_b_sum[i];
      total = total + chan_a_sum[i];
    }
    ave_a = ave_a/total;
    ave_b = ave_b/total;

    printf("\n Glink errors = %d %d %d %d\n",
	   glink_err_sum[0], glink_err_sum[1], glink_err_sum[2], glink_err_sum[3]);
    printf("\n Cap ids = %d %d %d %d\n",
	   cap_id_sum[0], cap_id_sum[1], cap_id_sum[2], cap_id_sum[3]);
    printf("\n Channel A average = %.2f\n", ave_a);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[0],  chan_a_sum[1],
	      chan_a_sum[2] , chan_a_sum[3]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[4],  chan_a_sum[5],
	      chan_a_sum[6] , chan_a_sum[7]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[8],  chan_a_sum[9],
	      chan_a_sum[10] , chan_a_sum[11]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[12],  chan_a_sum[13],
	      chan_a_sum[14] , chan_a_sum[15]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[16],  chan_a_sum[17],
	      chan_a_sum[18] , chan_a_sum[19]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[20],  chan_a_sum[21],
	      chan_a_sum[22] , chan_a_sum[23]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[24],  chan_a_sum[25],
	      chan_a_sum[26] , chan_a_sum[27]);
    printf(" %10d %10d %10d %10d\n", chan_a_sum[28],  chan_a_sum[29],
	      chan_a_sum[30] , chan_a_sum[31]);

  printf("\n");

    printf(" Channel B average = %.2f\n", ave_b);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[0],  chan_b_sum[1],
	      chan_b_sum[2] , chan_b_sum[3]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[4],  chan_b_sum[5],
	      chan_b_sum[6] , chan_b_sum[7]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[8],  chan_b_sum[9],
	      chan_b_sum[10] , chan_b_sum[11]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[12],  chan_b_sum[13],
	      chan_b_sum[14] , chan_b_sum[15]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[16],  chan_b_sum[17],
	      chan_b_sum[18] , chan_b_sum[19]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[20],  chan_b_sum[21],
	      chan_b_sum[22] , chan_b_sum[23]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[24],  chan_b_sum[25],
	      chan_b_sum[26] , chan_b_sum[27]);
    printf(" %10d %10d %10d %10d\n", chan_b_sum[28],  chan_b_sum[29],
	      chan_b_sum[30] , chan_b_sum[31]);

#endif

  printf("\n");
#ifdef PACKAGE_MODE
  //read trailer word count
  rc = fread(data, 4, 1, fp);
  //  printf("trailer count = %d\n", data[0]);
  while(1){ 
   rc = fread(ic, 4, data[0]-1, fp);
   //   printf("trailer read rc=%d  first word=%d\n", rc, ic[0]);
   if(rc > 0) {
     ic[rc*4]='\0';
     printf("%s",ic);
   } else break;
  }
  printf("\n");
  printf("\n");

#endif

    close(fp);

  return 0;
}
