/* ana subroutines and functions for decoding TRACE dp headers */
#include "defs.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include "ana_structures.h"
 /* for SGI only (?) */
#if __sgi
#include  <malloc.h>
#endif
#define ABS(x) ((x)>=0?(x):-(x))
#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))
#define X_INT(x,n)  (((int) x[n+1]) & 0xff) +	\
       ((((int) x[n])<<8 )& 0xff00) +		\
       ((((int) x[n+3])<<16 )& 0xff0000) +	\
       ((((int) x[n+2])<<24 )& 0xff000000)
#define X_INT2(x,n)  (((int) x[n+3]) & 0xff) +	\
       ((((int) x[n+2])<<8 )& 0xff00) +		\
       ((((int) x[n+1])<<16 )& 0xff0000) +	\
       ((((int) x[n])<<24 )& 0xff000000)
#define X_SHORT(x,n)  (((int) x[n+1]) & 0xff) +	\
       ((((int) x[n])<<8 )& 0xff00)

 extern	int scrat[NSCRAT];
 extern	struct sym_desc sym[];
 extern  int     ana_type_size[];
 static unsigned int bitmask[] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f,
 0x7f, 0xff, 0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff};
 static unsigned int bits[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,
 	8192,16384,32768};
 typedef struct Keywords {
  /* probably want to make this a linked list that gets read in but make
  it fixed for prototype */
  char	*name;
  short	type;
  short special;
  int	start_bit;
  int	num_bits;
  //struct Keywords	  *next;	/* the link to next one */
  } Keywords;
 /* the basic TRACE parameters, most are types 1 or 2 (I*2 or I*4) except
 for some requiring special processing (like the time_tai), the special
 field is used to determine what kind of special processing */
 Keywords	basics[] = {
 "time_tai", 4,  1, 3*16, 48,
 "seqid",    2,  0, 198*16, 32,
 "fn_inseq", 1,  0, 201*16, 16,
 "frm_num",  2,  0, 202*16, 32,
 "trgid",    1,  0, 205*16, 16,
 "frmid",    1,  0, 294*16, 16,
 "mseqid",   1,  0, 244*16, 16,
 "xsum",     1,  0, 102*16+8, 8,
 "ysum",     1,  0, 103*16, 8,
 "amp",     1,  0, 102*16+4, 1,
 };
 int  nkeywords = sizeof(basics)/sizeof(Keywords);
 /*------------------------------------------------------------------------- */
int head_error(n)
 int	n;
 {
 printf("DECODE_HEADER - ");
 switch (n) {
  case 0:
   printf("start bit non-zero for 16 or 32 bit extraction\n");
   break;
  case 1:
   printf("result type error\n");
   break;
  case 2:
   printf("unknown special case\n");
   break;
  default:
   printf("unknown error\n");
   break;
  }
 return -1;
 }
 /*------------------------------------------------------------------------- */
int ana_show_header(narg,ps)			/* show_header */
 /* the call is show_header, dp_head, [k]
    where array must be a dp header array, either 1-D or 2-D, pre-amble
    is the first part of the output variables (which are top level and
    normally should be globals)
    k is the image in the header to show, if omitted, all are listed */
 /* this is primarily a test code */
 int	narg, ps[];
 {
 int	nx, ny, nd, i, iq, type, nk, npreamble, sl, new_sym, ndim_var;
 int	dim_var[8], start, j,sign_flag, width, *pvar_int, temp, ik, n, k;
 int	seqid, fn_inseq, frm_num, trgid, frmid, mseqid, xsum, amp;
 int	ix, iy, ix2, iy2, nx_ccd, ny_ccd, bm, stat;
 int	quad_encoder, quad, f1, f2, w1, w2, focus, wave;
 float	xsun,ysun,xoff,yoff,trace_xc,trace_yc,trace_pixel_size,trace_exp;
 double	dq, tai;
 short	mask, *pvar_short;
 char	*dp_ptr, *phead;
 char	*ppq, *sq, *q, *qb;
 struct	ahead	*h;
 /* get the dp header, some checks */
 iq = ps[0];
 if ( sym[iq].class != 4 ) return execute_error(66);
 type = sym[iq].type;
 if (type != 1) return execute_error(111); /* must be I*2 */
 h = (struct ahead *) sym[iq].spec.array.ptr;
 /* dp headers can be 1-D (for a single image) or higher, the result uses
 all the higher dimensions */
 nd = h->ndim;
 nx = h->dims[0];  ny = 1;  ndim_var = 1;
 /* need a byte count for nx, we may have a I*2 internal type passed
 but we work with byte pointer (mostly to handle different endians */
 nx = nx * ana_type_size[type];
 dim_var[0] = 1;
 if (nd > 1) {
  ny = 1; for (i=1;i<nd;i++) { ny*= h->dims[i];  dim_var[i-1] = h->dims[i]; }
  ndim_var = nd - 1;
  }
 dp_ptr = (char *) ((char *)h + sizeof(struct ahead));
 k = 0;
 if (narg > 1) { /* single image case */
   if (int_arg_stat(ps[1], &k) != 1) return -1;
   if (k >= ny) {
     printf("image number %d out of range\n", k);
     return 0; }
   ny = 1;	 /* just the one */
   }
 
 stat = show_header(dp_ptr, k, ny);
 
 return stat;
 }
 /*------------------------------------------------------------------------- */
int ana_decode_header(narg,ps)			/* decode_header */
 /* the call is decode_header, dp_head, [pre-amble], [index array]
    where array must be a dp header array, either 1-D or 2-D, pre-amble
    is the first part of the output variables (which are top level and
    normally should be globals) */
 int	narg, ps[];
 {
 int	nx, ny, nd, i, iq, type, nk, npreamble, sl, new_sym, ndim_var;
 int	dim_var[8], start, j,sign_flag, width, *pvar_int, temp, ik, n;
 short	mask, *pvar_short;
 char	*dp_ptr, *phead, *preamble, *def_preamble = "$TH_";
 char	*ppq, *sq, *q, *qb;
 struct	ahead	*h;
 /* get the dp header, some checks */
 iq = ps[0];
 if ( sym[iq].class != 4 ) return execute_error(66);
 type = sym[iq].type;
 if (type != 1) return execute_error(111); /* must be I*2 */
 h = (struct ahead *) sym[iq].spec.array.ptr;
 /* dp headers can be 1-D (for a single image) or higher, the result uses
 all the higher dimensions */
 nd = h->ndim;
 nx = h->dims[0];  ny = 1;  ndim_var = 1;
 /* need a byte count for nx, we may have a I*2 internal type passed
 but we work with byte pointer (mostly to handle different endians */
 nx = nx * ana_type_size[type];
 dim_var[0] = 1;
 if (nd > 1) {
  ny = 1; for (i=1;i<nd;i++) { ny*= h->dims[i];  dim_var[i-1] = h->dims[i]; }
  ndim_var = nd - 1;
  }
 dp_ptr = (char *) ((char *)h + sizeof(struct ahead));
 preamble = def_preamble;
 if (narg > 1) {
  if ( sym[ ps[1] ].class != 2 ) return execute_error(70);
  preamble = (char *) sym[ps[1] ].spec.array.ptr;
  }
 npreamble = strlen(preamble);
 
 printf("nkeywords = %d, ny = %d\n", nkeywords, ny);

 /* the basic ones first */
 for (ik = 0; ik < nkeywords; ik++) {
  /* construct the variable name */
  sl = npreamble + strlen(basics[ik].name);
  sq = (char *) malloc(sl + 1);
  strcpy(sq, preamble);  strcat(sq, basics[ik].name);
  ppq = sq;  while (sl--) *ppq++ = toupper(*ppq);
  new_sym = find_sym(sq);
  printf("variable name = %s, symbol # %d\n", sq, new_sym);
  free(sq);
  /* create the array */
  type = basics[ik].type;
  if (redef_array(new_sym, type, ndim_var, dim_var) != 1)
     { printf("TRACE_HEADER - error creating variable\n");
     return -1; }
  h = (struct ahead *) sym[new_sym].spec.array.ptr;
  q = qb = (char *) ((char *)h + sizeof(struct ahead));
  
  /* the bit stuff for this variable */
  start = basics[ik].start_bit;
  width = basics[ik].num_bits;
  j = start/16;
  start = start%16;
  //printf("j, 2*j = %d, %d\n", j, 2*j);
  //printf("nx = %d\n", nx);
  phead = (dp_ptr + 2*j); /* point to our first byte */
  //printf("*phead = %#x, %#x, %#x, %#x\n", phead[0], phead[1], phead[2], phead[3]);
  n = ny;

  /* check for our special cases */
  
  if (!basics[ik].special) {

  /* drop out for 2 easy cases, the 16 and 32 bit widths
  these must have start = 0 though */
  //printf("width = %d\n", width);
  switch (width) {
  
  case 32:
   //printf("32 section\n");
   /* the 32 bit values are cryptically stored in a non-standard order,
   neither big nor little endian */
   if (start) return head_error(0);
   /* only type 2 output for this case */
   //printf("type = %d\n", type);
   if (type != 2) return head_error(1);
   pvar_int = (int *) q;
   while (n--) {
     *pvar_int++ = (((int) phead[1]) & 0xff) +
     		  ((((int) phead[0])<<8 )& 0xff00) +
     		  ((((int) phead[3])<<16 )& 0xff0000) +
     		  ((((int) phead[2])<<24 )& 0xff000000);
     //printf("value = %d, %#x\n", *(pvar_int-1), *(pvar_int-1) );
     phead += nx; }
   break;
  case 16:
   //printf("16 section\n");
   if (start) return head_error(0);
   /* only 2 types supported */
   switch (type) {
   case 1:  pvar_short = (short *) q;
    while (n--) { 
      *pvar_short++ = (((short) phead[1]) & 0xff) +
     	           ((((short) phead[0])<<8 )& 0xff00);
      phead += nx; }
    break;
   case 2:  pvar_int = (int *) q;
    while (n--) {
      *pvar_int++ = (((int) phead[1]) & 0xff) +
     	           ((((int) phead[0])<<8 )& 0xff00);
      phead += nx; }
    break;
   default: return head_error(1);
   }
   break;
  default:
   printf("default section\n");
   /* only type 1 output for this case
   if (type != 1) return head_error(1);
   if (width < 0) { width = - width;  sign_flag = 1; } else sign_flag = 0;
   mask = bitmask[width];
   j = start;	/* our shift */
   pvar_short = (short *) q;
   /* loop over the "images" */
   while (n--) {
    iq = (int) *phead;
    iq = (iq >> j) & mask;
    if (sign_flag) {
     /* messy, but probably not used too often */
    if (iq & bits[width-1]) {
	 /* the top bit of the bit field is set, so need to extend it */
	 iq = iq | ( 0xffffffff - mask); } }
    *pvar_short++ = (short) iq;
    phead += nx;
    }
   break;
 }

 } else {
 /* special cases here */
 /* only one so far, the tai */
 switch (basics[ik].special) {
  case 1:
   /* the tai case, we take 48 bits combined in a very creative way */
   {
   double *pvar_doub, dq, tq;
   pvar_doub = (double *) q;
   /* loop over the "images" */
   while (n--) {
    /* the first 32 bits are the integer seconds in big endian style
    the 3rd 16 bit field is the fractional seconds */
    iq = (((int) phead[3]) & 0xff) +
     	 ((((int) phead[2])<<8 )& 0xff00) +
     	 ((((int) phead[1])<<16 )& 0xff0000) +
     	 ((((int) phead[0])<<24 )& 0xff000000);
    //printf("iq = %d, %#x\n", iq,iq);
    dq = (double) iq;
    iq = (((int) phead[5]) & 0xff) +
     	 ((((int) phead[4])<<8 )& 0xff00);
    dq = dq + ((double) iq)/65536. - 271641594.0 + 25.0 ;
    *pvar_doub++ = dq;
    phead += nx;
    }
   }
   break;
  default: return head_error(2);
 }
 }
 }
 return 1;
 }
 /*------------------------------------------------------------------------- */
