#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif

#include "rs232.h"


void time_date(void)
{
   time_t currenttime;

   currenttime=time(NULL);

   printf("%ld sec ", (long)currenttime);
   printf("UTC %s\n", asctime(gmtime(&currenttime)));

}


time_t my_timegm(register struct tm * t)
/* struct tm to seconds since Unix epoch */
{
    register long year;
    register time_t result;
#define MONTHSPERYEAR   12      /* months per calendar year */
    static const int cumdays[MONTHSPERYEAR] =
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };

    /*@ +matchanyintegral @*/
    year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR;
    result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR];
    result += (year - 1968) / 4;
    result -= (year - 1900) / 100;
    result += (year - 1600) / 400;
    if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
        (t->tm_mon % MONTHSPERYEAR) < 2)
        result--;
    result += t->tm_mday - 1;
    result *= 24;
    result += t->tm_hour;
    result *= 60;
    result += t->tm_min;
    result *= 60;
    result += t->tm_sec;
    if (t->tm_isdst == 1)
        result -= 3600;
    /*@ -matchanyintegral @*/
    return (result);
}


int datac16;
long int datac32;
unsigned long long datau64;

int main()
{
  int i, n,  e_rbuf, s_rbuf, n_b, j,
      cport_nr=0,        /* /dev/ttyS0 (COM1 on windows) */
      bdrate=38400;       /* 9600 baud */

  unsigned char abuf[4096], rbuf[8192], buf[50], sbuf[100];


  char mode[]={'8','N','1',0};

  char kc;

    unsigned char rtcday,rtcmonth,rtcyear,lastrtcday;

    unsigned char cbuffer[256], cdatas[16], cdatas2[16];
    int s_cnt;
    double mx_s,my_s,mz_s;
    time_t currenttime, timertc;
    struct tm * ptm;
    struct tm tinfo;


    double time_1,time_c, time_l, mul_t;
    double fadj;//time per tick

    double tdelta, tdelta1, tevents, tevent_base, tmean, n_event, mean_n;
    double p_mbar,t_c;
    unsigned char tb, mreset,reset1;
    unsigned long long ltb,ltime_c,lmul_t, ltime_l;

    char debug;

    FILE *fd=NULL;
    FILE *fdev=NULL;

    char filenamepath[256]="c:\\werkstatt\\";
    char filenamedevpath[256]="c:\\werkstatt\\";
    char filename[256];
    char filenamedev[256];


  time_1=-100.0;
  fadj=1/16e6;
  mean_n=5; //how many averages for running mean?
  tmean=0.0;
  tevent_base=0.1; //prox time per event - for counting

  mreset=1;//resets mean calc

  tevents=0.0;

  if(RS232_OpenComport(cport_nr, bdrate, mode))
  {
    printf("Can not open comport\n");

    return(0);
  }


  printf("Nominal interval (s): %0.8f\n",tevent_base);
  printf("<x> to exit, <r> to reset\n");
//  printf("Intervals: ravg%0.0f ppm s/day - tavg   ppm   s/day\n",mean_n);
  printf("Intervals: itime ravg%0.0f ppm s/day - total\n",mean_n);

  kc=0;

  e_rbuf=0;  //end buffer
  s_rbuf=0; //start buffer



  debug=0;

  while(kc!='x')
  {
    n = RS232_PollComport(cport_nr, abuf, 4095);

    if ((e_rbuf+n)>8100)
    {
        n=0;
        e_rbuf=0;
        s_rbuf=0;
        printf("***** buffer overflow! Buffer cleared!\n");
    }

    for(i=0; i < n; i++)
    {
      rbuf[i+e_rbuf]=abuf[i];
    }
    e_rbuf+=n;

    n_b=0; //characters in single data set buffer

    for(i=0; i < e_rbuf; i++)
    {
      if (rbuf[i]=='T')
      {
          s_rbuf=i;//make sure things move on if incorrect frame received
          if ((i+28)<e_rbuf) //one complete dataset received?
          {
            if (rbuf[i+28]=='E') //there are extreme unlikely cases that data could acutal be received as frame....
            {
               for (j=0;j<29;j++)
               {
                   buf[j]=rbuf[i+j];
               }
               n_b=28;
               buf[n_b]=0;
               s_rbuf=i+j;
               i=e_rbuf;
            } else { printf("***** incorrect frame!\n"); }

         }// else { printf("***** need more data!\n"); }
      }
    }

    for (i=0;i<(e_rbuf-s_rbuf);i++) //reorganize buffer
    {
        rbuf[i]=rbuf[s_rbuf+i];
    }
    e_rbuf=e_rbuf-s_rbuf;
    s_rbuf=0;


    if ((e_rbuf>0)&&(debug))
    {

      sbuf[e_rbuf] = 0;   // always put a "null" at the end of a string!

      for(i=0; i < e_rbuf; i++)
      {
        if(rbuf[i] < 32)  // replace unreadable control-codes by dots
        {
          sbuf[i] = '.';
        } else {sbuf[i]=rbuf[i];}
      }

      printf("rbuf %i bytes: >%s<\n", e_rbuf, (char *)sbuf);
    }


    if(n_b ==28)
    {


      sbuf[n_b] = 0;   // always put a "null" at the end of a string!

      for(i=0; i < n_b; i++)
      {
        if(buf[i] < 32)  // replace unreadable control-codes by dots
        {
          sbuf[i] = '.';
        }else {sbuf[i]=buf[i];}
        cbuffer[i]=buf[i];
      }

      if (debug) {printf("received %i bytes: %s\n", n_b, (char *)sbuf);}


            if (cbuffer[0]=='R')
           {
               //printf("Already captured!");
           } else
           {


           datac16=0;
           datac16|=cbuffer[25];
           datac16=datac16<<8;
           datac16|=cbuffer[26];
           printf("%d ",datac16);
           //fprintf(fd,"%d ",datac16);


           rtcday=cbuffer[12];
           rtcmonth=cbuffer[13];
           rtcyear=cbuffer[14];

           if (rtcday!=lastrtcday)
           {
              if (fd!=NULL) { fclose(fd);}
              if (fdev!=NULL) { fclose(fdev);}
              sprintf(filename,"%s%0.2d%0.2d%0.2dticdat.dat",filenamepath,rtcyear,rtcmonth,rtcday);
              sprintf(filenamedev,"%s%0.2d%0.2d%0.2dticdev.dat",filenamedevpath,rtcyear,rtcmonth,rtcday);
              fd = fopen(filename,"a");
              fdev = fopen(filenamedev,"a"); //time and frequency
              lastrtcday=rtcday;
           }

           printf("%02d:%02d:%02d ", cbuffer[9],cbuffer[10],cbuffer[11]);
           //printf("%02d.%02d.%02d ", cbuffer[12],cbuffer[13],cbuffer[14]);

           //fprintf(fd,"%02d:%02d:%02d ", cbuffer[9],cbuffer[10],cbuffer[11]);
           //fprintf(fd,"%02d.%02d.%02d ", cbuffer[12],cbuffer[13],cbuffer[14]);

           tinfo.tm_year = 2000+cbuffer[14] - 1900;
           tinfo.tm_mon = cbuffer[13]-1;
           tinfo.tm_mday = cbuffer[12];
           tinfo.tm_hour = cbuffer[9];
           tinfo.tm_min = cbuffer[10];
           tinfo.tm_sec = cbuffer[11];
           tinfo.tm_isdst = 0; //utc basis

           timertc = my_timegm(&tinfo); //utc

           //printf("%d %d\n",timertc);
           //fprintf(fd,"%d ",timertc);//unix utc time stamp


           datac16=0;
           datac16|=cbuffer[3];
           datac16=datac16<<8;
           datac16|=cbuffer[4];

           printf("%0.1f ", ((double)datac16)/10.0);
           t_c=((double)datac16)/10.0;
           //fprintf(fd,"%0.1f ", ((double)datac16)/10.0);

           datac32=0;
           datac32|=cbuffer[5];
           datac32=datac32<<8;
           datac32|=cbuffer[6];
           datac32=datac32<<8;
           datac32|=cbuffer[7];
           datac32=datac32<<8;
           datac32|=cbuffer[8];

		   printf("%0.2f ", ((double)datac32)/100.0);
		   p_mbar=((double)datac32)/100.0;
		   //fprintf(fd,"%0.2f ", ((double)datac32)/100.0);

           datau64=0;
		   datau64|=cbuffer[15];
		   datau64=datau64<<8;
		   datau64|=cbuffer[16];
		   datau64=datau64<<8;
		   datau64|=cbuffer[17];
		   datau64=datau64<<8;
		   datau64|=cbuffer[18];
		   datau64=datau64<<8;
		   datau64|=cbuffer[19];
		   datau64=datau64<<8;
		   datau64|=cbuffer[20];
		   datau64=datau64<<8;
		   datau64|=cbuffer[21];
		   datau64=datau64<<8;
		   datau64|=cbuffer[22];

           printf("%I64d %0.7f\n", datau64, ((double)datau64)/16e6);
           //fprintf(fd,"%I64d %0.7f\n", datau64, ((double)datau64)/16e6);
          // fprintf(fd,"%0.7f\n", ((double)datau64)/16e6);


           //time and drift calc
           time_c=((double)datau64);
           if (time_1<0.0) {time_1=time_c;}
           if (reset1) {
              time_1=time_c;
              mreset=1;
              tevents=0;
              reset1=0;
           }
           tdelta=(time_c-time_l)*fadj;


           if (time_c>time_1) {
            n_event=round(tdelta/tevent_base); //determine number of events

            if (n_event<1)
            {
               printf("Error! Interval was too short!\n");
            } //else {printf("%f events\n",n_event);}

            tevents+=n_event;
            if (mreset) {tmean=tdelta/n_event; mreset=0;}

            tmean=(tmean*mean_n+tdelta/n_event)/(mean_n+1.0);  //running mean

            if (((tmean/tevent_base)<0.9)||((tmean/tevent_base)>1.1)||(tmean!=tmean) )
            {
                mreset=1;
                tmean=-9999.0;
            }

            printf("%8.0f: %12.7f ** %12.7f  %8.3f %8.3f \n", tevents, tdelta/n_event, tmean, ((tmean-tevent_base)/tevent_base)*1e6,((tmean-tevent_base)/tevent_base)*24*3600/1.0);
            //fprintf(fdev,"%0.7f %0.7f\n", tdelta, tdelta-(n_event*tevent_base)); //sampling interval, phase deviation
            fprintf(fdev,"%0.0f %0.7f\n",tevents, (time_c-time_1)*fadj-(tevents*tevent_base)); //sampling interval, phase deviation

            fprintf(fd,"%0.0f %d ",tevents,timertc);//unix utc time stamp
            fprintf(fd,"%0.7f %0.1f %0.2f\n", ((double)datau64)/16e6,t_c,p_mbar);


           }
             time_l=time_c;



           //end time and drift calc

    }
    }
 if (kbhit()) { kc=getch();  if (kc=='r') {reset1=1;} }

if (e_rbuf<28) {

#ifdef _WIN32
    Sleep(100);
#else
    usleep(10000);  /* sleep for 10 milliSeconds */
#endif
}

  }

  fclose(fd);
  fclose(fdev);
  return(0);
}
