/* beamH2sdds					F. Lenkszus */
/* converts a raw beam history file to sdds format */
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "SDDS.h"

/*
#define DEBUG
*/

#define	MAX_IN 35000
#define SHORTPTR 1
#define LONGPTR 2

struct	rawdata {
	short	*x;
	short	*y;
	short	*xs;
	short	*ys;
	short	*xsum;
	short	*xsums;
	short	*ysum;
	short	*ysums;
	short	*xindex;
	short	*yindex;
	int32_t	*xt;
	int32_t	*xsumt;
	int32_t	*yt;
	int32_t	*ysumt;
	long	numx;
	long   numy;
	long	numsumx;
	long	numsumy;
};

int	readInFile( char *file, unsigned long *buf, int num);
int	callocDataStruct( void **p, int numptrs,  int numelem, int type);
int	crackBHdata( unsigned long *in, int num,  struct rawdata *p);

int main(int argc, char**argv)

{

int	i, num;
char	basename[128], outfilex[128], outfiley[128], infile[128];
unsigned long	*inbuf;
struct	rawdata rdata;
char	*ptr;
char	 *descript_text="Beam History Data";
char	*descript_contents_x = "X Position and Sum";
char	*descript_contents_y = "Y Position and Sum";
/*char	parameter[128];*/
SDDS_TABLE SDDS_table;
char	*version = "1.0, May, 1995";
char	*usage = 
"%s <inputfile>\n\
This program converts a beam history raw data file to SDDS format.\n\
The results are placed in files of the same base name as <inputfile> with\n\
an extensions of .sdds .  Separate files are created for x and y.\n\
Program by Frank Lenkszus ( Version %s.)\n";

if (argc != 2) {
	fprintf(stderr, usage, argv[0], version);
	exit(-1);
}
if( (inbuf=(unsigned long *)malloc(MAX_IN*sizeof(unsigned long))) == NULL) {
	fprintf(stderr,"Couldn't malloc %d unsigned longs\n", MAX_IN);
	exit(-1);
} 

if( (ptr=strchr(argv[1], (int)'.')) != NULL)
	*ptr=NULL;

strcpy(basename, argv[1]);
strcpy(infile, basename);
strcat(infile, ".raw");

if((num = readInFile( infile, inbuf, MAX_IN)) <= 0) {
	fprintf(stderr, "Error reading %s\n", infile);
	exit(-1);
}
#ifdef DEBUG
	printf("%d lines read in from %s\n", num, infile);
#endif
if(callocDataStruct( &(rdata.x), 10, num, SHORTPTR))
	exit(-1);
if(callocDataStruct( &(rdata.xt), 4, num, LONGPTR))
	exit(-1);

crackBHdata( inbuf, num,  &rdata);
for ( i = 0; i < rdata.numx; i++)
	rdata.xindex[i] = i;
for ( i = 0; i < rdata.numy; i++)
	rdata.yindex[i] = i;

#ifdef DEBUG
printBHdata(&rdata);
#endif

/* removed the used of fixed value parameter */
/* sprintf(parameter, "%d", rdata.numx); */

strcpy(outfilex, basename);
strcat(outfilex, "-x");
strcat(outfilex, ".sdds");


if( !SDDS_InitializeOutput(&SDDS_table, SDDS_BINARY, 0, descript_text,
	descript_contents_x, outfilex)) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if( 	SDDS_DefineParameter(&SDDS_table, "nrows", "NumRows", NULL,
		"Number of Rows", NULL, SDDS_LONG, NULL) < 0 ) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if(
	SDDS_DefineColumn(&SDDS_table, "index", "Index", NULL, 
		"Index", NULL, SDDS_SHORT, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "x", "x-pos", NULL, 
		"X position", NULL, SDDS_SHORT, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "xt", "x-turns", NULL, 
		"X Turns", NULL, SDDS_LONG, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "xsum", "x-sum", NULL, 
		"X Sum", NULL, SDDS_SHORT, 0) < 0 ||
      	SDDS_DefineColumn(&SDDS_table, "xsumt", "x-sum-turns", NULL, 
		"X Sum Turns", NULL, SDDS_LONG, 0) < 0 ||
      	SDDS_DefineColumn(&SDDS_table, "xsums", "x-sum-stat", NULL,
		"X Sum Status", NULL, SDDS_SHORT, 0) < 0 ) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if( !SDDS_WriteLayout(&SDDS_table) || 
   !SDDS_StartTable(&SDDS_table, num) ||
   !SDDS_SetParameters(&SDDS_table, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE,
                               "nrows", rdata.numx, NULL) ) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if(
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.xindex, rdata.numx,
	 "index") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.x, rdata.numx,
	 "x") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.xt, rdata.numx,
	 "xt") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.xsum, rdata.numx,
	 "xsum") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.xsumt, rdata.numx,
	 "xsumt") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.xsums, rdata.numx,
	 "xsums")) { 
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(1);
}



if( !SDDS_WriteTable(&SDDS_table) || !SDDS_Terminate(&SDDS_table)) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

/* removed the used of fixed value parameter */
/* sprintf(parameter, "%d", rdata.numy); */

strcpy(outfiley, basename);
strcat(outfiley, "-y");
strcat(outfiley, ".sdds");


if( !SDDS_InitializeOutput(&SDDS_table, SDDS_BINARY, 0, descript_text,
	descript_contents_y, outfiley)) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if( 	SDDS_DefineParameter(&SDDS_table, "nrows", "NumRows", NULL,
		"Number of Rows", NULL, SDDS_LONG, NULL) < 0 ) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if(
	SDDS_DefineColumn(&SDDS_table, "index", "Index", NULL, 
		"Index", NULL, SDDS_SHORT, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "y", "y-pos", NULL,
		"Y position", NULL, SDDS_SHORT, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "yt", "y-turns", NULL,
		"Y Turns", NULL, SDDS_LONG, 0) < 0 ||
	SDDS_DefineColumn(&SDDS_table, "ysum", "y-sum", NULL,
		"Y Sum", NULL, SDDS_SHORT, 0) < 0 ||
      	SDDS_DefineColumn(&SDDS_table, "ysumt", "y-sum-turns", NULL,
		"Y Sum Turns", NULL, SDDS_LONG, 0) < 0 ||
     	SDDS_DefineColumn(&SDDS_table, "ysums", "y-sum-stat", NULL,
		"Y Sum Status", NULL, SDDS_SHORT, 0) < 0 ) {
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if( !SDDS_WriteLayout(&SDDS_table) || 
   !SDDS_StartTable(&SDDS_table, num) ||
   !SDDS_SetParameters(&SDDS_table, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE,
                               "nrows", rdata.numy, NULL) ){
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}

if( 
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.yindex, rdata.numy,
	 "index") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.y, rdata.numy,
	 "y") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.yt, rdata.numy,
	 "yt") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.ysum, rdata.numy,
	 "ysum") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.ysumt, rdata.numy,
	 "ysumt") ||
      !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, rdata.ysums, rdata.numy,
	 "ysums")) { 
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(1);
}

if( !SDDS_WriteTable(&SDDS_table) || !SDDS_Terminate(&SDDS_table)){
      SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors);
	exit(-1);
}
return(0);
}

/**************************************************************************/
int	readInFile( char *file, unsigned long *buf, int num)
{
FILE	*fd;
int	numread;

if((fd = fopen(file, "r")) == NULL) {
	fprintf(stderr, "Couldn't open %s for read\n", file);
	return(-1);
}

numread = fread(buf, sizeof(unsigned long), num, fd);
fclose(fd);
return(numread);
}

/**************************************************************************/

int	callocDataStruct( void **p, int numptrs,  int numelem, int type)
{
int	i;
short	**sptr;
int32_t	**lptr;
char	*procname="mallocDataStruct";

switch (type) {
	case	SHORTPTR:
		sptr = (short **)p;
		for ( i=0; i < numptrs; i++, sptr++) {
			if( (*sptr=(short *)calloc(numelem,sizeof(short)))
				 == NULL) {
	      fprintf(stderr, "Couldn't allocate datastruct i = %d type = %d\n",
			 i, type);
				return(-1);
			}
		}
		break;
	case	LONGPTR:
		lptr = (int32_t **)p;
		for ( i=0; i < numptrs; i++, lptr++) {
			if( (*lptr=(int32_t *)calloc(numelem,sizeof(int32_t)))
				 == NULL) {
	      fprintf(stderr, "Couldn't allocate datastruct i = %d type = %d\n",
			 i, type);
				return(-1);
			}
		}
		break;
	default :
		fprintf(stderr, "%s: %d is not a recognized allocation type\n",
			procname, type);
		return(-1);
}
return(0);
} 

/***************************************************************************/

#define  SEARCH4XorY  1
#define  CHECK4Xsum   2
#define  CHECK4Ysum   3
#define	 DISCARD      4

int	crackBHdata( unsigned long *in, int num,  struct rawdata *p)

{

int	i;
int	state;
int	process;
short	stmp, stmp1;
long	ltmp;

p->numx = p->numy = p->numsumx = p->numsumy = 0;

state = SEARCH4XorY;
for ( i=0; i < num; i++) {
	process = 1;
	while(process) {
#ifdef DEBUGCRACK
		printf(" i = %d, input = %x, state =%d\n", i, in[i], state);
#endif
	   switch (state) {
		case  SEARCH4XorY :
			if((in[i] & 0x80000000) == 0x80000000) {
				process = 0;
				stmp = in[i] & 0xfff;
				       if(stmp & 0x800) /* sign extnd*/ 
						stmp |= 0xf000;
				ltmp = (in[i] & 0x3fffe000) >> 13;
				stmp1 = (in[i] & 0x1000) >> 12;
				if((in[i] & 0x40000000) == 0x40000000) {
					p->x[p->numx] = stmp;
					p->xt[p->numx] = ltmp;
					p->xs[p->numx] = stmp1;
					p->numx++;
					state = CHECK4Xsum;
				} else {
					p->y[p->numy] = stmp;
					p->yt[p->numy] = ltmp;
					p->ys[p->numy] = stmp1;
					p->numy++;
					state = CHECK4Ysum;
				}
			} else
				state = DISCARD;
		break;
		case  CHECK4Xsum :
			if((in[i] & 0x80000000) == 0x00000000) {
				p->xsum[p->numsumx] = in[i] & 0xfff;
				p->xsumt[p->numsumx]=(in[i] & 0x3fffe000) >> 13;
				if((in[i] & 0x40000000) == 0x40000000)
					p->xsums[p->numsumx] = 1;
				else	
					p->xsums[p->numsumx] = 0;
				p->numsumx++;
				process = 0;
			}
			state=SEARCH4XorY;
		break;
		case  CHECK4Ysum :
			if((in[i] & 0x80000000) == 0x00000000) {
				p->ysum[p->numsumy] = in[i] & 0xfff;
				p->ysumt[p->numsumy]=(in[i] & 0x3fffe000) >> 13;
				if((in[i] & 0x40000000) == 0x40000000)
					p->ysums[p->numsumy] = 1;
				else	
					p->ysums[p->numsumy] = 0;
				p->numsumy++;
				process = 0;
			}
			state=SEARCH4XorY;
		break;
		case  DISCARD :
			state=SEARCH4XorY;
			process = 0;
			break;
	   }
	}

}

return(0);

}

int	printBHdata( struct rawdata *p)
{
  int	i, num;
  
  printf("%ld x's, %ld sum x's, %ld y's, %ld sum y's found\n", p->numx,
	 p->numsumx, p->numy, p->numsumy);
  
  num =  p->numx > p->numsumx ? p->numx : p->numsumx;
  printf("index\tx\txturns\txsum\txsum-turns\tstatus\n");
  for ( i = 0; i < num; i++) 
    printf("%d\t%d\t%ld\t%d\t%ld\t%d\n", p->xindex[i], p->x[i],
	   p->xt[i], p->xsum[i], p->xsumt[i], p->xsums[i]);
  
  num =  p->numy > p->numsumy ? p->numy : p->numsumy;
  printf("index\ty\tyturns\tysum\tysum-turns\tstatus\n");
  for ( i = 0; i < num; i++) 
    printf("%d\t%d\t%ld\t%d\t%ld\t%d\n", p->yindex[i], p->y[i],
	   p->yt[i], p->ysum[i], p->ysumt[i], p->ysums[i]);

  return(0);
}
