/*---------------------------------------------------------------------------

 This program reads the reads the binary DS1 PEPE data files and
 prints their start/stop times to the screen.

rename WRITE_ASCII.C to WRITE_ASCII.c

 compilation:

     cc -O -o WRITE_ASCII -I. WRITE_ASCII.c

 usage:
       start_stop infile outfile type doy 

       where 
         infile  = input file name
         type    = 0 Electron
                 = 1 Ion
                 = 2 Time of Flight
                 = 3 Mass/Charge
                 = 4 Log
         doy     = day of year, Jan 1 = 1

---------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "PEPE.H"

int usage() {
   printf("\n");
   printf("\n");
   printf("usage: \n");
   printf("      start_stop infile outfile type doy \n");
   printf("\n");
   printf("      where \n");
   printf("        infile  = binary input file name\n");
   printf("        outfile = ascii output file name\n");
   printf("        type    = 0 Electrons\n");
   printf("                = 1 Ions\n");
   printf("                = 2 Time of Flight\n");
   printf("                = 3 Mass/Charge\n");
   printf("                = 4 Log\n");
   printf("                = 5 Housekeeping\n");
   printf("        doy     = day of year, Jan 1 = 1\n");
   printf("\n");
   printf("\n");
}

/*-----------------------------------------------------------
-----------------------------------------------------------*/
int fix_int(
   short seca,
   short secb)
{
  union {
    struct {
      int seca:16;
      int secb:16;
    } parts;
    int ival;
  } secs;

  secs.parts.seca = seca;
  secs.parts.secb = secb;
  return(secs.ival);
}
/*-----------------------------------------------------------
-----------------------------------------------------------*/
float fix_float(
   short seca,
   short secb)
{
  union {
    struct {
      int seca:16;
      int secb:16;
    } parts;
    float fval;
  } secs;

  secs.parts.seca = seca;
  secs.parts.secb = secb;
  return(secs.fval);
}

/*-----------------------------------------------------------
-----------------------------------------------------------*/
int swap_byte_2(unsigned short val)
{
  char tmp;
  union {
    struct {
      char parta;
      char partb;
    } parts;
    unsigned short ival;
  } secs;

  secs.ival = val; 
  tmp = secs.parts.parta;
  secs.parts.parta = secs.parts.partb;
  secs.parts.partb = tmp;
  val = secs.ival;
}

/*-----------------------------------------------------------
-----------------------------------------------------------*/
int swap_byte_4(unsigned int val)
{ 
  char tmpa, tmpb; 
  union { 
    struct { 
      char parta; 
      char partb; 
      char partc; 
      char partd; 
    } parts;    
    unsigned int ival; 
  } secs; 
  
  secs.ival = val;    
  tmpa = secs.parts.parta;
  tmpb = secs.parts.partb;
  secs.parts.parta = secs.parts.partd;
  secs.parts.partb = secs.parts.partc;
  secs.parts.partc = tmpb;
  secs.parts.partd = tmpa;
  val = secs.ival; 
} 

/*-----------------------------------------------------------
-----------------------------------------------------------*/
int make_time(
  int   doy,
  int   secs,
  short off,
  char *timestr)
{
  int start_sec = 0;
  int hour      = 0;
  int min       = 0;
  int sec       = 0;
  int day;
  float fsec    = sec;


  day       = doy;
  start_sec = secs + off;       /* Add record offset to start time */
  start_sec += 86400/2;         /* Account for J2000 starting at noon  */
  start_sec -= 86400*(doy-1);   /* Substract off days  */
  start_sec -= 31622400;        /* Subtract off seconds in year 2000 */
  hour      = start_sec/3600;   /* Get hours */
  start_sec -= hour*3600;
  min       = start_sec/60; 
  start_sec -= min*60;
  sec       = start_sec;
  if (hour >= 24) {
      hour  -= 24;
      day   += 1;
  }
  sprintf(timestr, "2001-%03dT%02d:%02d:%02d\0", day,hour,min,sec);
}

/*-----------------------------------------------------------
-----------------------------------------------------------*/
main (int argc, char *argv[])
{

  unsigned char inbuf[600];             /* "safull" input record */

  char infile[80];
  char outfile[80];
  char time[23];
  int  sec, sclk;
  int  i,j;
  int  cnt;
  int  type;
  int  doy;
  int  data[1024];
  float ips_level, rcs_sum;

  if (argc < 4) {
    usage();
  } else {
    strcpy(infile, argv[1]);
    strcpy(outfile, argv[2]);
    type = atoi(argv[3]);
    doy  = atoi(argv[4]);
  } 

  if((ifptr = fopen(infile, "rb")) == NULL) {
     printf("Unable to open input file %s (not found, permissions?). Fatal!\n",
             infile);
     exit(0);
  }   

  if((ofptr = fopen(outfile, "w")) == NULL) {
     printf("Unable to open output file %s (not found, permissions?). Fatal!\n",
             outfile);
     exit(0);
  }   

/*
  printf("ELECTRONS = %d  IONS = %d   TIMEOF = %d  MASSQ = %d  ANCIL = %d\n",
          sizeof(ELECTRONS), sizeof(IONS), sizeof(TIMEOF), 
          sizeof(MASSQ), sizeof(ANCIL));
*/

  cnt = 0;
  switch (type) {

    case ELE:

      while (fread(&ele, sizeof(ELECTRONS), 1, ifptr) != 0) {
         sec = fix_int(ele.secs[0], ele.secs[1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_2(ele.meas);
           swap_byte_2(ele.offset);
           swap_byte_2(ele.energy);
           swap_byte_2(ele.elev);
           for (i=0; i<4; i++) swap_byte_4(ele.azim[i]);
         }
         make_time(doy, sec, 0, time);
         fprintf(ofptr,"%5d %17s %8d %5d %2d %1d %7d %7d %7d %7d\n",
                   ele.meas, time, sec, ele.offset, ele.energy, ele.elev,
                   ele.azim[0], ele.azim[1], ele.azim[2], ele.azim[3]);
      }
      break; 

    case ION:

      while (fread(&ion, sizeof(IONS), 1, ifptr) != 0) {
         sec = fix_int(ion.secs[0], ion.secs[1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_2(ion.meas);
           swap_byte_2(ion.offset);
           swap_byte_2(ion.energy);
           swap_byte_2(ion.elev);
           for (i=0; i<8; i++) swap_byte_4(ion.azim[i]);
         }
         make_time(doy, sec, 0, time);
         fprintf(ofptr,"%5d %17s %8d %5d %2d %1d %7d %7d %7d %7d %7d %7d %7d %7d\n",
                   ion.meas, time, sec, ion.offset, 
                   ion.energy, ion.elev, ion.azim[0], ion.azim[1], 
                   ion.azim[2], ion.azim[3], ion.azim[4], ion.azim[5], 
                   ion.azim[6], ion.azim[7]); 

      }   
      break;

    case TOF:

      while (fread(&tof, sizeof(TIMEOF), 1, ifptr) != 0) {
         sec = fix_int(tof.secs[0], tof.secs[1]);
         for (i=0; i<1024; i++) data[i]=fix_int(tof.data[2*i],tof.data[2*i+1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_2(tof.meas);
           for (i=0; i<1024; i++)  swap_byte_4(data[i]);
         }
         make_time(doy, sec, 0, time);
         fprintf(ofptr,"%5d %17s %8d ",
                       tof.meas,time,sec); 
         for (i=0; i<1023; i++) fprintf(ofptr,"%7d ",data[i]); 
         fprintf(ofptr,"%7d\n", data[1023]);
      }   
      break;

    case MQ:

      while (fread(&mq, sizeof(MASSQ), 1, ifptr) != 0) {
         sec = fix_int(mq.secs[0], mq.secs[1]);
         for(i=0; i<15; i++) data[i] = fix_int(mq.data[2*i], mq.data[2*i+1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_2(mq.meas);
           swap_byte_2(mq.offset);
           swap_byte_2(mq.energy);
           for (i=0; i<15; i++) swap_byte_4(mq.data[i]);
         }
         make_time(doy, sec, 0, time);  
         fprintf(ofptr,"%5d %17s %8d %5d %2d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 
                    mq.meas,time, sec, mq.offset, mq.energy,
                    data[0] , data[1] , data[2] , data[3] , data[4],
                    data[5] , data[6] , data[7] , data[8] , data[9],
                    data[10], data[11], data[12], data[13], 
                    data[14]);
      }   
      break;

    case LOG:

      while (fread(&logs, sizeof(ANCIL), 1, ifptr) != 0) {
         sec = fix_int(logs.secs[0], logs.secs[1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_2(logs.meas);
           swap_byte_2(logs.offset);
           swap_byte_2(logs.energy);
           swap_byte_2(logs.elev);
           for (i=0; i<4; i++) swap_byte_4(logs.data[i]);
         }
         make_time(doy, sec, 0, time);
         fprintf(ofptr,"%5d %17s %8d %5d %2d %1d %7d %7d %7d %7d\n",
                   logs.meas, time, sec, logs.offset, logs.energy, logs.elev,
                   logs.data[0], logs.data[1], logs.data[2], logs.data[3]);
      }   
      break;

    case HSK:

      printf("WARNING: Errors will occur in the floating point fields if\n");
      printf("         your system does not use IEEE floating point.\n");

      while (fread(&hsk, sizeof(HOUSE), 1, ifptr) != 0) {
         sec       = fix_int(hsk.secs[0], hsk.secs[1]);
         sclk      = fix_int(hsk.sclk[0], hsk.sclk[1]);
         ips_level = fix_float(hsk.ips_level[0], hsk.ips_level[1]);
         rcs_sum   = fix_float(hsk.rcs_sum[0], hsk.rcs_sum[1]);
         if (LSB) {
           swap_byte_4(sec);
           swap_byte_4(sclk);
           swap_byte_2(hsk.int_time);
           swap_byte_2(hsk.ips_on);
           swap_byte_4(ips_level);
           swap_byte_4(rcs_sum);
           swap_byte_2(hsk.sun_az);
           swap_byte_2(hsk.sun_el);
         }
         make_time(doy, sec,  0, time);
         fprintf(ofptr,"%5d %17s %8d %8d %2d %2d %7.4f %6.3f %3d %3d\n",
                  hsk.meas, time, sec, sclk, hsk.int_time, hsk.ips_on,
                  ips_level, rcs_sum, hsk.sun_az, hsk.sun_el);
      }
      break;

  }
}
