#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <fftw3.h>
#include <alsa/asoundlib.h>

#include "fano.h"
#include "wsprd_utils.h"
//#include "wsprsim_utils.h"
#define GNUPLOT "gnuplot -persist"
//#define GNUPLOT "gnuplot "

#define max(x,y) ((x) > (y) ? (x) : (y))
// Possible PATIENCE options: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT,
// FFTW_MEASURE, FFTW_PATIENT, FFTW_EXHAUSTIVE
#define PATIENCE FFTW_ESTIMATE
fftwf_plan PLAN1,PLAN2,PLAN3;

unsigned char pr3[162]=
{1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,
    0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,
    0,0,0,0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1,
    1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,
    0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0,
    0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1,
    0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1,
    0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,
    0,0};

unsigned long nr;
int printdata=0;
int iterasi = 0;

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

unsigned long readwavfile(char *infile, float *idat, float *qdat )

{
  FILE *fp;
  FILE *fgambar,*gg,*gh;
  char gambar_fname0[200];
  char gambar_fname6[200];
  char header[44];
  
  size_t i, j, npoints;
  int nfft1, nfft2, nh2, i0;
  double df;

  int16_t *buf2_int16, *buf2;   // buffer integer 16bits
  float *buf2_float;

  int rtime =114 ; // 114 detik estimasi jitter transmisi WSPR
  int buffer_frames_48 = rtime*48000; // alokasi buffer samping 48KHz sesuai jumlah sampel
  int buffer_frames_12 = rtime*12000; // alokasi buffer sampleing 12 KHz

  //  infile=malloc(40*sizeof(char));
  buf2 = malloc(buffer_frames_48 * 4);
  buf2_int16 = malloc(buffer_frames_48 * 2);
  buf2_float = malloc(buffer_frames_48*sizeof(float));
   

  //  printf("\n%s\n",infile);
  if(strstr(infile,".raw")==NULL && strstr(infile,".WAV")==NULL ){
    printf("\nAnda tidak memasukkan argumen dengan benar..!!!!\n\n");
    exit(1);
  } 
  if(strstr(infile,".raw") ){
    fp = fopen(infile,"rb");
    if (fp == NULL) {
      fprintf(stderr, "\nTidak ada file %s... \n",infile);
      exit(1);
    }

    nr=fread(buf2,4,buffer_frames_48,fp);       //Read raw data
    fclose(fp);


  /* ambil 1 sampel mono  */

  for (i = 0; i < buffer_frames_48; i++){
    buf2[i]=buf2[2*i];
 }
  /**********************/

  /* anti aliasing filter  */

  float pi = 3.141592654; 
  float fc = 2500;
  float frq=48000;
  float a1,b1,c1,tau1;

  tau1=1/(2*pi*fc);
  a1=(1.0-1.0/(2.0*tau1*frq))/(1.0+1.0/(2.0*tau1*frq));
  b1=c1=(1.0/(2.0*tau1*frq))/(1.0+1.0/(2.0*tau1*frq));

  buf2_int16[0]=buf2[0];
  buf2_float[0]=(float)buf2[0];
  for (i = 1; i < buffer_frames_48; i++){
    buf2_float[i]=a1*buf2_float[i-1]+b1*(float)buf2[i]+c1*(float)buf2[i-1];
    buf2_int16[i]=(int16_t)buf2_float[i];
  }
  /*************************/

  /**** decimasi menjadi 12 KHz sampling ***/

  for (i = 0; i < buffer_frames_12; i++){
    buf2_int16[i] = buf2_int16[i*4];
  }
  /*
  for (i = buffer_frames_12; i < buffer_frames_48; i++){
    buf2_int16[i] = 0;
  }
  */
  
  /*****************************************/
  }

  else  if(strstr(infile,".WAV") != 0){
    fp = fopen(infile,"rb");
    if (fp == NULL) {
      fprintf(stderr, "\nTidak ada  file %s... \n",infile);
      exit(1);
    }

    nr=fread(header,2,22,fp);            //Read and ignore header
    nr=fread(buf2_int16,2,buffer_frames_12,fp);       //Read raw data
    fclose(fp);
  }
                                                                   
  /*
  for (i = 0; i < buffer_frames_12; i++){
    if(i>100000){
      printf("buf2_int16[%d]= %d\n",i,buf2_int16[i]);
      getchar();
    }
  }
  */


  nfft2=46080; /* ini adalah jumlah sampel setelah proses downsampling */
  nh2=nfft2/2;
    

  nfft1=nfft2*32;      //need to downsample by a factor of 32
  df=12000.0/nfft1;
  i0=1500.0/df+0.5;
  npoints=114*12000;

    
  float *realin;
  fftwf_complex *fftin, *fftout;
    
    realin=(float*) fftwf_malloc(sizeof(float)*nfft1);
    fftout=(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*(nfft1/2+1));
    PLAN1 = fftwf_plan_dft_r2c_1d(nfft1, realin, fftout, PATIENCE);
    
    for (i=0; i<npoints; i++) {
      realin[i]=buf2_int16[i]/32768.0;
    }
    
    if((gh = popen(GNUPLOT,"w"))==NULL){ /* 'gh' is the pipe descriptor */
      printf("Error opening pipe to GNU plot. Check if you have it! \n");
      exit(0);
    }

    strcpy(gambar_fname6,"./gambar6.tmp");
    if((fgambar = fopen(gambar_fname6,"w")) == NULL) {
      fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname6);
      return 1;
    }

    for (i=50000; i<50300; i++) {
      fprintf(fgambar,"%d %f\n",i, realin[i]);
    }
    fclose(fgambar);    
    fprintf(gh, "plot './gambar6.tmp'  lt 1 with lines title 'segmen sinyal'\n");


    for (i=npoints; i<(size_t)nfft1; i++) {
        realin[i]=0.0;
    }
    
    free(buf2);
    free(buf2_int16);
    free(buf2_float);
    fftwf_execute(PLAN1);
    fftwf_free(realin);

    if((gg = popen(GNUPLOT,"w"))==NULL){ /* 'gg' is the pipe descriptor */
      printf("Error opening pipe to GNU plot. Check if you have it! \n");
      exit(0);
    }
    strcpy(gambar_fname0,"./gambar0.tmp");
    if((fgambar = fopen(gambar_fname0,"w")) == NULL) {
      fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname0);
      return 1;
    }

    double cetak;
    for (i=0; i<(size_t)nfft1/2; i++) {
      cetak = fftout[i][0]*fftout[i][0]+fftout[i][1]*fftout[i][1];
      cetak = 10*log10(cetak); 
      fprintf(fgambar,"%f %f\n",df*i, cetak);
    }
    fclose(fgambar);    
    fprintf(gg, "plot './gambar0.tmp'  lt 1 with lines title 'spektrum seluruh sinyal dgn BW 6000 Hz'\n");
    //    fflush(gg);
    //    getchar();

    fftin=(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*nfft2);

    for (i=0; i<(size_t)nfft2; i++) {
      j=i0+i;                            /* i0===1500Hz; -nh2----->i0----->nh2,   nfft2=2nh2  */
      if( i>(size_t)nh2 ) j=j-nfft2;
      fftin[i][0]=fftout[j][0];
      fftin[i][1]=fftout[j][1];
    }
    fftwf_free(fftout);

    fftout=(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*nfft2);
    PLAN2 = fftwf_plan_dft_1d(nfft2, fftin, fftout, FFTW_BACKWARD, PATIENCE);
    fftwf_execute(PLAN2);
    
    for (i=0; i<(size_t)nfft2; i++) {
        idat[i]=fftout[i][0]/1000.0;
        qdat[i]=fftout[i][1]/1000.0;
    }

    fftwf_free(fftin);
    fftwf_free(fftout);
    fclose(gg);
    fclose(gh);
    return nfft2;
}

//***************************************************************************
void sync_and_demodulate(float *id, float *qd, long np,
                         unsigned char *symbols, float *f1, int ifmin, int ifmax, float fstep,
                         int *shift1, int lagmin, int lagmax, int lagstep,
                         float *drift1, int symfac, float *sync, int mode)
{
  /*********************************************************************************
     * mode = 0: tanpa pencarian frekuensi atau drift. Dapatkan time lag terbaik    *
     *        1: tanpa pencarian time lag dan  drift. Dapatkan frekuensi terbaik    *
     *******************************************************************************/
    
    static float fplast=-10000.0;
    static float dt=1.0/375.0, df=375.0/256.0;
    static float pi=3.14159265358979323846;
    float twopidt, df15=df*1.5, df05=df*0.5;

    int i, j, k, lag;
    float i0[162],q0[162],i1[162],q1[162],i2[162],q2[162],i3[162],q3[162];
    float p0,p1,p2,p3,cmet,totp,syncmax;
    float c0[256],s0[256],c1[256],s1[256],c2[256],s2[256],c3[256],s3[256];
    float dphi0, cdphi0, sdphi0, dphi1, cdphi1, sdphi1, dphi2, cdphi2, sdphi2, dphi3, cdphi3, sdphi3;
    float f0=0.0, fp, ss, fbest=0.0;
    int best_shift = 0, ifreq;

    syncmax=-1e30;
    if( mode == 0 ) {ifmin=0; ifmax=0; fstep=0.0; f0=*f1;}
    if( mode == 1 ) {lagmin=*shift1;lagmax=*shift1;f0=*f1;}
    
    twopidt=2*pi*dt;
    for(ifreq=ifmin; ifreq<=ifmax; ifreq++) {
        f0=*f1+ifreq*fstep;
        for(lag=lagmin; lag<=lagmax; lag=lag+lagstep) {
            ss=0.0;
            totp=0.0;
            for (i=0; i<162; i++) {
	      fp = f0 + (*drift1/2.0)*((float)i-81.0)/81.0;  //ini rumus frekuensi drift linier
                if( i==0 || (fp != fplast) ) {  // generator sin/cos cepat
                    dphi0=twopidt*(fp-df15);
                    cdphi0=cos(dphi0);
                    sdphi0=sin(dphi0);
                    
                    dphi1=twopidt*(fp-df05);
                    cdphi1=cos(dphi1);
                    sdphi1=sin(dphi1);
                    
                    dphi2=twopidt*(fp+df05);
                    cdphi2=cos(dphi2);
                    sdphi2=sin(dphi2);
                    
                    dphi3=twopidt*(fp+df15);
                    cdphi3=cos(dphi3);
                    sdphi3=sin(dphi3);
                    
                    c0[0]=1; s0[0]=0;
                    c1[0]=1; s1[0]=0;
                    c2[0]=1; s2[0]=0;
                    c3[0]=1; s3[0]=0;


                    for (j=1; j<256; j++) {
                        c0[j]=c0[j-1]*cdphi0 - s0[j-1]*sdphi0;
                        s0[j]=c0[j-1]*sdphi0 + s0[j-1]*cdphi0;
                        c1[j]=c1[j-1]*cdphi1 - s1[j-1]*sdphi1;
                        s1[j]=c1[j-1]*sdphi1 + s1[j-1]*cdphi1;
                        c2[j]=c2[j-1]*cdphi2 - s2[j-1]*sdphi2;
                        s2[j]=c2[j-1]*sdphi2 + s2[j-1]*cdphi2;
                        c3[j]=c3[j-1]*cdphi3 - s3[j-1]*sdphi3;
                        s3[j]=c3[j-1]*sdphi3 + s3[j-1]*cdphi3;
                    }

		      /* generator sin/cos standar */

		    /*
                    for (j=1; j<256; j++) {
			c0[j]=cos(dphi0*(double)j);
			s0[j]=sin(dphi0*(double)j);
			c1[j]=cos(dphi1*(double)j);
			s1[j]=sin(dphi1*(double)j);
			c2[j]=cos(dphi2*(double)j);
			s2[j]=sin(dphi2*(double)j);
			c3[j]=cos(dphi3*(double)j);
			s3[j]=sin(dphi3*(double)j);
                    }
		    */
                    fplast = fp;
                }
                
                i0[i]=0.0; q0[i]=0.0;
                i1[i]=0.0; q1[i]=0.0;
                i2[i]=0.0; q2[i]=0.0;
                i3[i]=0.0; q3[i]=0.0;
                
                for (j=0; j<256; j++) {
                    k=lag+i*256+j;
                    if( (k>0) && (k<np) ) {      /* np = 46080 */
                        i0[i]=i0[i] + id[k]*c0[j] + qd[k]*s0[j];
                        q0[i]=q0[i] - id[k]*s0[j] + qd[k]*c0[j];
                        i1[i]=i1[i] + id[k]*c1[j] + qd[k]*s1[j];
                        q1[i]=q1[i] - id[k]*s1[j] + qd[k]*c1[j];
                        i2[i]=i2[i] + id[k]*c2[j] + qd[k]*s2[j];
                        q2[i]=q2[i] - id[k]*s2[j] + qd[k]*c2[j];
                        i3[i]=i3[i] + id[k]*c3[j] + qd[k]*s3[j];
                        q3[i]=q3[i] - id[k]*s3[j] + qd[k]*c3[j];
                    }
                }
                p0=i0[i]*i0[i] + q0[i]*q0[i];
                p1=i1[i]*i1[i] + q1[i]*q1[i];
                p2=i2[i]*i2[i] + q2[i]*q2[i];
                p3=i3[i]*i3[i] + q3[i]*q3[i];

                p0=sqrt(p0);
                p1=sqrt(p1);
                p2=sqrt(p2);
                p3=sqrt(p3);
                
                totp=totp+p0+p1+p2+p3;
                cmet=(p1+p3)-(p0+p2);
                ss = (pr3[i] == 1) ? ss+cmet : ss-cmet;
	    }
            ss=ss/totp;
            if( ss > syncmax ) {          //simpan paramater terbaik
                syncmax=ss;
                best_shift=lag;
                fbest=f0;
            }
        } // lag loop
    } //freq loop
    
    if( mode <=1 ) {                       // kirim kembali parameter terbaik kepada caller 
        *sync=syncmax;
        *shift1=best_shift;
        *f1=fbest;
        return;
    }
    
    return;
}

void noncoherent_sequence_detection(float *id, float *qd, long np,
                         unsigned char *symbols, float *f1,  int *shift1,
                         float *drift1, int symfac, int *nblocksize)
{

    static float fplast=-10000.0;
    static float dt=1.0/375.0, df=375.0/256.0;
    static float pi=3.14159265358979323846;
    float twopidt, df15=df*1.5, df05=df*0.5;
    
    int i, j, k, lag, itone, b, nblock, nseq;
    float xi[512],xq[512];
    float is[4][162],qs[4][162];
    float p[512],fac;
    float c0[257],s0[257],c1[257],s1[257],c2[257],s2[257],c3[257],s3[257];
    float dphi0, cdphi0, sdphi0, dphi1, cdphi1, sdphi1, dphi2, cdphi2, sdphi2,
    dphi3, cdphi3, sdphi3;
    float f0, fp, fsum=0.0, f2sum=0.0, fsymb[162];

    
    twopidt=2*pi*dt;
    f0=*f1;
    lag=*shift1;
    nblock=*nblocksize;
    nseq=1<<nblock;

    for (i=0; i<162; i++) {
        fp = f0 + (*drift1/2.0)*((float)i-81.0)/81.0;
        if( i==0 || (fp != fplast) ) {  // generator sin/cos cepat
            dphi0=twopidt*(fp-df15);
            cdphi0=cos(dphi0);
            sdphi0=sin(dphi0);
                    
            dphi1=twopidt*(fp-df05);
            cdphi1=cos(dphi1);
            sdphi1=sin(dphi1);
                    
            dphi2=twopidt*(fp+df05);
            cdphi2=cos(dphi2);
            sdphi2=sin(dphi2);
                    
            dphi3=twopidt*(fp+df15);
            cdphi3=cos(dphi3);
            sdphi3=sin(dphi3);
                    
            c0[0]=1; s0[0]=0;
            c1[0]=1; s1[0]=0;
            c2[0]=1; s2[0]=0;
            c3[0]=1; s3[0]=0;
                    

            for (j=1; j<257; j++) {
                c0[j]=c0[j-1]*cdphi0 - s0[j-1]*sdphi0;
                s0[j]=c0[j-1]*sdphi0 + s0[j-1]*cdphi0;
                c1[j]=c1[j-1]*cdphi1 - s1[j-1]*sdphi1;
                s1[j]=c1[j-1]*sdphi1 + s1[j-1]*cdphi1;
                c2[j]=c2[j-1]*cdphi2 - s2[j-1]*sdphi2;
                s2[j]=c2[j-1]*sdphi2 + s2[j-1]*cdphi2;
                c3[j]=c3[j-1]*cdphi3 - s3[j-1]*sdphi3;
                s3[j]=c3[j-1]*sdphi3 + s3[j-1]*cdphi3;
            }

	    /*generator sin/cos standar */

	    /*
	      for (j=0; j<257; j++) {
	      c0[j]=cos(dphi0*(double)j);
	      s0[j]=sin(dphi0*(double)j);
	      c1[j]=cos(dphi1*(double)j);
	      s1[j]=sin(dphi1*(double)j);
	      c2[j]=cos(dphi2*(double)j);
	      s2[j]=sin(dphi2*(double)j);
	      c3[j]=cos(dphi3*(double)j);
	      s3[j]=sin(dphi3*(double)j);
	      }
	    */
            fplast = fp;   /* sekedar penanda sampai pada baris ini */
	}

        is[0][i]=0.0; qs[0][i]=0.0;
        is[1][i]=0.0; qs[1][i]=0.0;
        is[2][i]=0.0; qs[2][i]=0.0;
        is[3][i]=0.0; qs[3][i]=0.0;

	
        for (j=0; j<256; j++) {
            k=lag+i*256+j;
            if( (k>0) && (k<np) ) {
                is[0][i]=is[0][i] + id[k]*c0[j] + qd[k]*s0[j];
                qs[0][i]=qs[0][i] - id[k]*s0[j] + qd[k]*c0[j];
                is[1][i]=is[1][i] + id[k]*c1[j] + qd[k]*s1[j];
                qs[1][i]=qs[1][i] - id[k]*s1[j] + qd[k]*c1[j];
                is[2][i]=is[2][i] + id[k]*c2[j] + qd[k]*s2[j];
                qs[2][i]=qs[2][i] - id[k]*s2[j] + qd[k]*c2[j];
                is[3][i]=is[3][i] + id[k]*c3[j] + qd[k]*s3[j];
                qs[3][i]=qs[3][i] - id[k]*s3[j] + qd[k]*c3[j];
            }
	}
    }

    /* ========== nseq=2, nblock=1 =========  */

    double tmpp[2],ctp0,ctp1,ctp2,ctp3;
    int pr3tmp;
    for (i=0; i<162; i=i+nblock) {
      for (j=0;j<nseq;j++) {
	xi[j]=0.0; xq[j]=0.0;

	b=j;
	itone=pr3[i]+2*b;
	xi[j]=xi[j]+is[itone][i] ; //nilai korelasi infase
	xq[j]=xq[j]+qs[itone][i] ; //nilai korelasi quadratur
            
	p[j]=xi[j]*xi[j]+xq[j]*xq[j];
	p[j]=sqrt(p[j]);
	//	tmpp[0][j]=p[j];
      }
      for (j=0;j<nseq;j++) {
	xi[j]=0.0; xq[j]=0.0;

	b=j;
	if(pr3[i]==0)pr3tmp=1;
	if(pr3[i]==1)pr3tmp=0;
	itone=pr3tmp+2*b;
	xi[j]=xi[j]+is[itone][i] ; //nilai korelasi infase
	xq[j]=xq[j]+qs[itone][i] ; //nilai korelasi quadratur
            
	tmpp[j]=xi[j]*xi[j]+xq[j]*xq[j];
	tmpp[j]=sqrt(p[j]);
      }
      
      if(pr3[i]==0){
	ctp0=p[0];
	ctp2=p[1];
	ctp1=tmpp[0];
	ctp3=tmpp[1];
      }
      if(pr3[i]==1){
	ctp1=p[0];
	ctp3=p[1];
	ctp0=tmpp[0];
	ctp2=tmpp[1];
      }
      printf("pr3[%d]= %d ctp0= %.2f; ctp2= %.2f; ctp1= %.2f; ctp3= %.2f\n",i,pr3[i],ctp0,ctp2,ctp1,ctp3);
      //      getchar();
      /**************************************************/
      /* hipotesis --> fsymb[i]== besar == 1; kecil== 0 */
      fsymb[i]=p[1]-p[0];   
      /**************************************************/
    }
    for (i=0; i<162; i++) {              //Normalize the soft symbols
      fsum=fsum+fsymb[i]/162.0;
      f2sum=f2sum+fsymb[i]*fsymb[i]/162.0;
    }
    fac=sqrt(f2sum-fsum*fsum);
    for (i=0; i<162; i++) {
      fsymb[i]=symfac*fsymb[i]/fac;
      if( fsymb[i] > 127) fsymb[i]=127.0;
      if( fsymb[i] < -128 ) fsymb[i]=-128.0;
      symbols[i]=fsymb[i] + 128;
      //      printf("[%d]= %u; ",i,symbols[i]);
    }
    getchar();
    iterasi++;

    /* plot simbol */ 



    if(iterasi==1){
      FILE *fgambar, *gx;
      char gambar_fname7[200];
      strcpy(gambar_fname7,"./gambar7.tmp");
      if((fgambar = fopen(gambar_fname7,"w")) == NULL) {
	fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname7);
	return ;
      }
      for (i=0; i<162; i++ ) {
	fprintf(fgambar,"%d %d\n",i,symbols[i]);
      }
      fclose(fgambar);
      if((gx = popen(GNUPLOT,"w"))==NULL){ 
	printf("Error opening pipe to GNU plot. Check if you have it! \n");
	exit(0);
      }
      fprintf(gx, "plot './gambar7.tmp' with impulses lt 16 title '162 simbol sebelum deinterleave' \n");
      fflush(gx);
      //      getchar();
      }


      /* end plot simbol */

    return;
}

//***************************************************************************
int main(int argc, char *argv[])
{
    char cr[] = "(C) 2018, Steven Franke - K9AN";
    (void)cr;
    extern char *optarg;
    extern int optind;
    int i,j,k;
    unsigned char *symbols, *decdata, *channel_symbols;
    signed char message[]={-9,13,-35,123,57,-39,64,0,0,0,0};
    char *callsign, *call_loc_pow;
    //    char *ptr_to_infile,*ptr_to_infile_suffix;

    char infile[50];
    char *data_dir=NULL;
    char spots_fname[200];
    char timer_fname[200];
    char gambar_fname1[200];
    char gambar_fname2[200];
    char gambar_fname3[200];
    char gambar_fname4[200];
    char gambar_fname5[200];
    char gambar_prob[200];
    
    char uttime[7],date[11];
    int delta,maxpts=65536;
    int writenoise=0, nblocksize;
    int maxdrift;
    int shift1, lagmin, lagmax, lagstep, ifmin, ifmax, worth_a_try, not_decoded;
    unsigned int nbits=81;
    unsigned int npoints, metric, cycles, maxnp;
    float df=375.0/256.0/2;
    float freq0[200],snr0[200],drift0[200],sync0[200];
    int shift0[200];
    float dt=1.0/375.0, dt_print;
    double dialfreq_cmdline=0.0, dialfreq, freq_print;
    double dialfreq_error=0.0;
    float fmin=-110, fmax=110;
    float f1, fstep, sync1, drift1;
    float psavg[512];
    float *idat, *qdat;
    clock_t t0,t00;
    float tfano=0.0,treadwav=0.0,tcandidates=0.0,tsync0=0.0;
    float tsync1=0.0,tsync2=0.0,ttotal=0.0;
    
    time_t t = time(NULL);
    struct tm tm = *localtime(&t);
    struct result { char date[11]; char time[6]; float sync; float snr;
                    float dt; double freq; char message[23]; float drift;
                    unsigned int cycles; int jitter; int blocksize; unsigned int metric; };
    struct result decodes[50];
    
    symbols=calloc(nbits*2,sizeof(char));
    decdata=calloc(11,sizeof(char));
    channel_symbols=calloc(nbits*2,sizeof(char));
    callsign=calloc(13,sizeof(char));
    call_loc_pow=calloc(23,sizeof(char));
    float allfreqs[100];
    char allcalls[100][13];
    for (i=0; i<100; i++) allfreqs[i]=0.0;
    memset(allcalls,0,sizeof(char)*100*13);
    
    int uniques=0, noprint=0;
    
    // Parameters used for performance-tuning:
    unsigned int maxcycles=10000;            //Decoder timeout limit
    float minsync1=0.10;                     //First sync limit
    float minsync2=0.12;                     //Second sync limit
    int iifac=8;                             //Step size in final DT peakup
    int symfac=50;                           //Soft-symbol normalizing factor
    //    int block_demod=1;                       //Default is to use block demod on pass 2
    //    int subtraction=1;
    //    int npasses=2;
       //       int npasses=1;

    float minrms=52.0 * (symfac/64.0);      //Final test for plausible decoding
    delta=60;                                //Fano threshold step
    float bias=0.45;                        //Fano metric bias (used for both Fano and stack algorithms)
    
    t00=clock();
    fftwf_complex *fftin, *fftout;
#include "./metric_tables.c"
    
    int mettab[2][256];
    
    if(argc < 2){
      printf("ketik argumen sebagai nama file dengan ext .raw atau .WAV .....\n\n");
      exit(1);
    }

    strcpy(infile, argv[1]);
    idat=calloc(maxpts,sizeof(float));
    qdat=calloc(maxpts,sizeof(float));
    
    //ptr_to_infile=argv[1];

    FILE *fwsprd, *ftimer, *fgambar, *gp, *gs,*gw, *fprob;
    strcpy(spots_fname,".");
    strcpy(timer_fname,".");
    strcpy(gambar_fname1,"./gambar1.tmp");
    strcpy(gambar_fname2,"./gambar2.tmp");
    strcpy(gambar_fname3,"./gambar3.tmp");
    strcpy(gambar_fname4,"./gambar4.tmp");
    strcpy(gambar_fname5,"./gambar5.tmp");
    strcpy(gambar_prob,"./gambarprob.txt");


    if(data_dir != NULL) {
        strcpy(spots_fname,data_dir);
        strcpy(timer_fname,data_dir);
    }

    strncat(spots_fname,"/wspr_spots.txt",20);
    strncat(timer_fname,"/wspr_timer.out",20);
    
    if((fprob = fopen(gambar_prob,"w")) == NULL) {
      fprintf(stderr, "Cannot open data file '%s'....\n", gambar_prob);
      exit(1);
    }

    for(i=0; i<256; i++) {
        mettab[0][i]=round( 10*(metric_tables[2][i]-bias) );
        mettab[1][i]=round( 10*(metric_tables[2][255-i]-bias) );
	fprintf(fprob, "Prob(%d|0) = %d; Prob(%d|1) =  %d\n",i, mettab[0][i], i, mettab[1][i]);
	//	printf("\nmt[2][%d]= %f; mt[2][%d]= %f\n", i, metric_tables[2][i], 255-i, metric_tables[2][255-i]);
	//	getchar();
    }
    fclose(fprob);    

    fwsprd=fopen(spots_fname,"w");
    //  FILE *fdiag;
    //  fdiag=fopen("wsprd_diag","a");
    
    /*
    if((ftimer=fopen(timer_fname,"r"))) {
        //Accumulate timing data
        nr=fscanf(ftimer,"%f %f %f %f %f %f %f",
                  &treadwav,&tcandidates,&tsync0,&tsync1,&tsync2,&tfano,&ttotal);
        fclose(ftimer);
    }
    */
    ftimer=fopen(timer_fname,"w");
    
    //    ptr_to_infile_suffix=strstr(ptr_to_infile,".wav");
        
    t0 = clock();
    npoints=readwavfile(infile,idat, qdat);
    treadwav += (float)(clock()-t0)/CLOCKS_PER_SEC;
    
    if( npoints == 1 ) {
      return 1;
    }
    dialfreq=dialfreq_cmdline - (dialfreq_error*1.0e-06);


    // Parse date and time from given filename
    //    strncpy(date,ptr_to_infile_suffix-11,6);
    //    strncpy(uttime,ptr_to_infile_suffix-4,4);
    //    date[6]='\0';
    //    uttime[4]='\0';

    // Do windowed ffts over 2 symbols, stepped by half symbols
    int nffts=4*floor(npoints/512)-1;

    fftin=(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*512);
    fftout=(fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*512);
    PLAN3 = fftwf_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE);
    
    float ps[512][nffts];
    float w[512];
    for(i=0; i<512; i++) {
        w[i]=sin(0.006147931*i);
    }
    

    //*************** main loop starts here *****************

    nblocksize=1;
    maxdrift=4;
    minsync2=0.12;

    // nffts=359
    //1 blok = 256
    //2 blok = 512
    // 1/2 blok = 128
    
    if((gp = popen(GNUPLOT,"w"))==NULL){ /* 'gp' is the pipe descriptor */
      printf("Error opening pipe to GNU plot. Check if you have it! \n");
      exit(0);
    }

    int gmb;
    for (i=0; i<nffts; i++) {

      for(j=0; j<512; j++ ) {
	k=i*128+j;
	fftin[j][0]=idat[k] * w[j];
	fftin[j][1]=qdat[k] * w[j];
      }
      fftwf_execute(PLAN3);
      
      /* spectrum swap   */
      for (j=0; j<512; j++ ) {
	k=j+256;
	if( k>511 )
	  k=k-512;
	ps[j][i]=fftout[k][0]*fftout[k][0]+fftout[k][1]*fftout[k][1];
      }


      if(i==130){
	gmb=i;
	if((fgambar = fopen(gambar_fname1,"w")) == NULL) {
	  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname1);
	  return 1;
	}
	for (j=0; j<512; j++ ) {
	  //	  fprintf(fgambar, "%f %f\n",j*df,(ps[j][i])*100);
	  fprintf(fgambar, "%f %f\n",j*df,10*log10((ps[j][i])*100));
	}
	fclose(fgambar);

      }
    }
    fprintf(gp, "plot './gambar1.tmp' lw 3 lt 16 with lines title 'spektrum simbol ke %d (BW 387 Hz)'\n",gmb);
    fflush(gp);
    //    getchar();


    // hitung  average spektrum
    //	double logpsavg;

        for (i=0; i<512; i++) psavg[i]=0.0;
        for (i=0; i<nffts; i++) {
            for (j=0; j<512; j++) {
                psavg[j]=psavg[j]+ps[j][i];
            }
	}

	if((fgambar = fopen(gambar_fname2,"w")) == NULL) {
	  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname2);
	  return 1;
	}


        for (i=0; i<512; i++)
	  fprintf(fgambar, "%f %f\n",i*df,10*log10(psavg[i]));
	fclose(fgambar);
	fprintf(gp, "replot './gambar2.tmp'  lw 3 lt 12 with lines title 'Rerata spektrum semua simbol (BW 387 Hz)'\n");
	fflush(gp);
	//	getchar();

	/***  Smoothing  dengan  7-point window dan dibatasi spectrum to +/-150 Hz ***/
        int window[7]={1,1,1,1,1,1,1};
        float smspec[411];

	float plot[411],xplot=7;
        for (i=0; i<411; i++) {
            smspec[i]=0.0;
	    plot[i]=0.0;
            for(j=-3; j<=3; j++) {
	      k=256-205+i+j;         /* digeser ke kiri sebesar 51 point */
	                             /* frekuensi tengah digeser dari 187,5 Hz ke 150 Hz */
		smspec[i]=smspec[i]+(window[j+3]*psavg[k]);
		plot[i]=plot[i] + (window[j+3]*psavg[k]/xplot); /* xplot hanya untuk 
							       keperluan ploting */
            }
	}

	if((fgambar = fopen(gambar_fname3,"w")) == NULL) {
	  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname3);
	  return 1;
	}

        for (i=0; i<411; i++)
	  fprintf(fgambar, "%f %f\n",i*df,10*log10(plot[i]));
	fclose(fgambar);
	fprintf(gp, "replot './gambar3.tmp' lw 3 with lines title 'spektrum digeser ke pusat observasi 150 Hz dan lebar observasi dibatasi 300 Hz' \n");
	fflush(gp);
	//	getchar();
        /*****************************************************************************/


        /**** urutkan nilai  spektrum, kemudian ambil level noise dalam betuk prosentase  **/
        float tmpsort[411];
        for (j=0; j<411; j++) {
            tmpsort[j]=smspec[j];
        }
        qsort(tmpsort, 411, sizeof(float), floatcomp);

	float psnr[411];
        for (j=0; j<411; j++) {
	  psnr[j]=10*log10(tmpsort[j]);
        }

        /*** estimasi level Noise dari spektrum adalah prosentase harga ke 123/411= 30'th ***/
        float noise_level = tmpsort[122];
        /*************************************************************************/        
        /* Renormalize spectrum so that (large) peaks represent an estimate of snr.
         * We know from experience that threshold snr is near -7dB in wspr bandwidth,
         * corresponding to -7-26.3=-33.3dB in 2500 Hz (3000 Hz...?) bandwidth.
         * The corresponding threshold is -42.3 dB in 2500 Hz bandwidth for WSPR-15. */
        
        float min_snr, snr_scaling_factor;
//        min_snr = pow(10.0,-7.0/10.0); //this is min snr in wspr bw
        min_snr = pow(10.0,-8.0/10.0); //this is min snr in wspr bw

	//	snr_scaling_factor=26.3;  // asumsi BW kanal 2500 Hz
	snr_scaling_factor=27.3;        // asumsi BW kanal 3000 Hz

        for (j=0; j<411; j++) {
            smspec[j]=smspec[j]/noise_level - 1.0;
            if( smspec[j] < min_snr) smspec[j]=0.1*min_snr;
            continue;
        }
        
        /*** mencari lokal maksimum dalam smoothed spectrum.  ***/
	/*** menghitung SNR untuk setiap lokal maksimum       ***/

        for (i=0; i<200; i++) {
            freq0[i]=0.0;
            snr0[i]=0.0;
            drift0[i]=0.0;
            shift0[i]=0;
            sync0[i]=0.0;
        }
        
        /* min_snr = pow(10.0,-8.0/10.0);  */
        int npk=0;
        unsigned char candidate;
	float fplot[100],pplot[200];
	for(j=1; j<410; j++) {
	  candidate = (smspec[j]>smspec[j-1]) &&
	    (smspec[j]>smspec[j+1]) &&
	    (npk<200);
	  if ( candidate ) {
	    freq0[npk]=(j-205)*df; /* freq0[npk] adalah frekuensi relatif 
				      terhadap 150 Hz (i=205) kekiri(-) atau kekanan (+) */
	    fplot[npk]=j*df;    /* hanya untuk keperluan ploting */
	    pplot[npk]=plot[j]; /* hanya untuk keperluan ploting */
	    snr0[npk]=10*log10(smspec[j])-snr_scaling_factor;
	    npk++;
	  }
	}
	
	/*********************************************************/

        /*** jangan buang waktu untuk sinyal diluar rentang [fmin,fmax].  ***/
	/*              fmin = -110 Hz; fmax = +110 Hz                      */
	printf("npk= %d\n",npk);

        i=0;
	for( j=0; j<npk; j++) {
	  if( freq0[j] >= fmin && freq0[j] <= fmax ) {
	    freq0[i]=freq0[j];
	    fplot[i]=fplot[j];  /* hanya untuk keperluan ploting */
	    pplot[i]=pplot[j];  /* hanya untuk keperluan ploting */
	    snr0[i]=snr0[j];
	    i++;
	  }
        }
        npk=i;
        
	printf("npk diantara +/-110 Hz= %d\n",npk);

	if((fgambar = fopen(gambar_fname4,"w")) == NULL) {
	  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname4);
	  return 1;
	}

        for( j=0; j<npk; j++) {
	  fprintf(fgambar, "%f %f\n",fplot[j],10*log10(pplot[j]));
	}
	fclose(fgambar);
	fprintf(gp, "replot './gambar4.tmp' lw 3 lt 1 with circles title 'kandidat frekuensi pusat'\n");
	fflush(gp);

	

	if((fgambar = fopen(gambar_fname5,"w")) == NULL) {
	  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_fname5);
	  return 1;
	}

        for( j=0; j<411; j++) {
	    fprintf(fgambar, "%d %f\n",j,psnr[j]);
	}
	fclose(fgambar);

	if((gs = popen(GNUPLOT,"w"))==NULL){ /* 'gs' is the pipe descriptor */
	    printf("Error opening pipe to GNU plot. Check if you have it! \n");
	    exit(0);
	}
	fprintf(gs, "plot './gambar5.tmp' lt 1 with impulses title 'SNR tipikal'\n");
	fflush(gs);
	fclose(gs);

	//	exit(0);             /* Terminal PRAKTIKUM-4 */


        /** sortir berdasarkan snr, selebar wilayah frekuensi observasi  ***/
        int pass;
        float tmp;
        for (pass = 1; pass <= npk - 1; pass++) {
            for (k = 0; k < npk - pass ; k++) {
                if (snr0[k] < snr0[k+1]) {
                    tmp = snr0[k];
                    snr0[k] = snr0[k+1];
                    snr0[k+1] = tmp;
                    tmp = freq0[k];
                    freq0[k] = freq0[k+1];
                    freq0[k+1] = tmp;
                }
	    }
	}
        t0=clock();


	printf("%5s%10s%10s\n","Cand","Freq0","SNR0");
	for(pass=0;pass<npk;pass++)
	  printf("%5d%10.4f%10.4f\n",pass+1,freq0[pass],snr0[pass]);
	getchar();


	/* Melaksanakan estimasi kasar terhadap ingsutan waktu (DT), freq dan drift,  */
	/* Time offset dibuat +/- 8 simbol (atau +/- 5,4 detik) relatif terhadap      */
	/* waktu start nominal, yang merupakan 2 detik kedalam file.             f    */ 
	/* Menghitung ingsut relatif terhadap awal file,                              */ 
	/* Ingsut negatif artinya bahwa sinyal berawal sebelum awal file              */
	/* Program akan mem-Printf DT = (shift-2) detik                               */
	/* Ingsutan tersebut menyebabkan sync-vector kehilangan data,                 */
	/* yang menghasilkan nilai 128 saat partial decoding dalam                    */ 
	/* proses soft-decision                                                       */
        /* Drift frekuensi dimodelkan secara linear, deviasi +/- drift/2 sepanjang    */
	/* 162 simbol dengan asumsi deviasi 0 pada pusat sinyal vektor (81)           */


        int idrift,ifr,if0,ifd,k0;
        int kindex;
        float smax,ss,pow,p0,p1,p2,p3;

        for(j=0; j<npk; j++) {                              /* untuk semua kandidat frekuensi */
            smax=-1e30;
            if0=freq0[j]/df+256;  /* dikembalikan ke frekuensi semula --> 
				     dari relatif terhadap 150 Hz (indeks 205) 
				     menjadi relatif terhadap 187,5 Hz (indeks 256) */
            for (ifr=if0-2; ifr<=if0+2; ifr++) {                  //Freq search
                for( k0=-10; k0<22; k0++) {                       //Time search
		  for (idrift=-maxdrift; idrift<=maxdrift; idrift++) {  /* Drift search, maxdrift=4 */
                        ss=0.0;
                        pow=0.0;
                         for (k=0; k<162; k++) {                             //Sum over symbols
                            ifd=ifr+((float)k-81.0)/81.0*( (float)idrift )/(2.0*df);
                            kindex=k0+2*k;
                            if( kindex < nffts ) {
			      p0=ps[ifd-3][kindex];
			      p1=ps[ifd-1][kindex];
			      p2=ps[ifd+1][kindex];
			      p3=ps[ifd+3][kindex];
                                
			      p0=sqrt(p0);
			      p1=sqrt(p1);
			      p2=sqrt(p2);
			      p3=sqrt(p3);
			      
			      ss=ss+(2*pr3[k]-1)*((p1+p3)-(p0+p2));
			      pow=pow+p0+p1+p2+p3;
			    }
			 }
                        sync1=ss/pow;
                        if( sync1 > smax ) {                  /** simpan parameter kasar **/
                            smax=sync1;
                            shift0[j]=128*(k0+1);
                            drift0[j]=idrift;
                            freq0[j]=(ifr-256)*df;
                            sync0[j]=sync1;
			}
		    } 
                }
            }
	}

        tcandidates += (float)(clock()-t0)/CLOCKS_PER_SEC;
	//	tcandidates = (float)(clock()-t0)/CLOCKS_PER_SEC;

	//		exit(0);     /* PERCOBAAN 5  */


        /*
         Rafinasi dari estimasi freq, shift dengan mamakai sync sebagai ukuran.
         Sync dihitung dengan rentang harga mengambang [0.0,1.0].
         
         Fungsi sync_and_demodulate memiliki 3 moda operasi
         moda ada pada argumen terakhir :
         
         0 = tanpa pencarian frequensi atau drift. Hanya mencari ingsut waktu (lag).
         1 = tanpa pencarian ingsut waktu (lag) atau  drift frekuensi. 
	 Hanya mencari frequensi terbaik.
         */


        for (j=0; j<npk; j++){
	  printf("frek[%d]= %f; shift[%d]= %d; sync[%d]= %f\n",j,freq0[j],j,shift0[j],j, sync0[j]);
	}

	getchar();
	
        for (j=0; j<npk; j++) {
	  
	  printf("\nKANDIDAT FREK KE: %d [%f];\n",j,freq0[j]);

            memset(symbols,0,sizeof(char)*nbits*2);
            memset(callsign,0,sizeof(char)*13);
            memset(call_loc_pow,0,sizeof(char)*23);

            f1=freq0[j];
            drift1=drift0[j];
            shift1=shift0[j];
            sync1=sync0[j];

            /* pencarian-kasar ingsut waktu (lag) dan frekuensi, 
	       kemudian sync>minsync1 continue **/
            fstep=0.0; ifmin=0; ifmax=0;
            lagmin=shift1-128;
            lagmax=shift1+128;
            lagstep=64;
            t0 = clock();

	    /* npoints = 46080  */
	    float tmpf1[7];int tmpshift1[7];float tmpdrift1[7]; float tmpsync1[7]; 
	    for(i=0;i<7;i++){
	      tmpf1[i]=0;
	      tmpshift1[i]=0;
	      tmpdrift1[i]=0;
	      tmpsync1[i]=0;
	    }
	    tmpf1[0]=f1;tmpshift1[0]=shift1;tmpdrift1[0]=drift1;tmpsync1[0]=sync1;
            sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
                                lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0);

            tsync0 += (float)(clock()-t0)/CLOCKS_PER_SEC;
	    //            tsync0 = (float)(clock()-t0)/CLOCKS_PER_SEC;

            fstep=0.25; ifmin=-2; ifmax=2;
            t0 = clock();
	    tmpf1[1]=f1;tmpshift1[1]=shift1;tmpdrift1[1]=drift1;tmpsync1[1]=sync1;
            sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
                                lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1);
	    tmpf1[2]=f1;tmpshift1[2]=shift1;tmpdrift1[2]=drift1;tmpsync1[2]=sync1;

	      /** rafinasi estimasi frekuensi  drift **/
	    fstep=0.0; ifmin=0; ifmax=0;
	    float driftp,driftm,syncp,syncm;
	    driftp=drift1+0.5;
	    sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
                                lagmin, lagmax, lagstep, &driftp, symfac, &syncp, 1);

	    driftm=drift1-0.5;
	    sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
                                lagmin, lagmax, lagstep, &driftm, symfac, &syncm, 1);
            
	    if(syncp>sync1) {
	      drift1=driftp;
	      sync1=syncp;
	    } else if (syncm>sync1) {
	      drift1=driftm;
	      sync1=syncm;
	    }

	    tmpf1[3]=f1;tmpshift1[3]=shift1;tmpdrift1[3]=drift1;tmpsync1[3]=sync1;

            tsync1 += (float)(clock()-t0)/CLOCKS_PER_SEC;
	    //            tsync1 = (float)(clock()-t0)/CLOCKS_PER_SEC;

	    /*************************************************/
            /** pencarian-halus frekuensi dan ingsut waktu  **/
	    /*************************************************/

            if( sync1 > minsync1 ) {         //minsync1=0.1
        
	      lagmin=shift1-32; lagmax=shift1+32; lagstep=16;
	      t0 = clock();
	      sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
				  lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0);
	      tmpf1[4]=f1;tmpshift1[4]=shift1;tmpdrift1[4]=drift1;tmpsync1[4]=syncp;



		tsync0 += (float)(clock()-t0)/CLOCKS_PER_SEC;
		//		                tsync0 = (float)(clock()-t0)/CLOCKS_PER_SEC;
            
                /* pencarian halus  frequensi  **/
                fstep=0.05; ifmin=-2; ifmax=2;
                t0 = clock();
                sync_and_demodulate(idat, qdat, npoints, symbols, &f1, ifmin, ifmax, fstep, &shift1,
                                lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1);

		tmpf1[5]=f1;tmpshift1[5]=shift1;tmpdrift1[5]=drift1;tmpsync1[5]=sync1;

                tsync1 += (float)(clock()-t0)/CLOCKS_PER_SEC;
		//            tsync1 = (float)(clock()-t0)/CLOCKS_PER_SEC;
		
                worth_a_try = 1;
	    }
	    else{
	      worth_a_try = 0;
	    }
            
	    printf("\nUpdate besaran freq1 shift1 dan drift1 dan sync1\n");
	    printf("%5s%10s%7s%8s\n","Freq0","Shift1","Drift1","Sync1");
	    for(i=0;i<6;i++)
	      printf("%7.4f%5d%10.4f%10.4f\n",tmpf1[i],tmpshift1[i],tmpdrift1[i],tmpsync1[i]);

	    printf("\n\n");
	    //	    exit(0);       /* PRAKTIKUM-6 */

	    // ada update harga shift1 dan drift1

            int idt, ii, jittered_shift;
            float y,sq,rms;
            not_decoded=1;
            int blocksize;  
	    /* iifac = 8 --> Step size in final DT peakup **/
	    /* nblocksize = 1 */

                blocksize=nblocksize;
                idt=0; ii=0;
		int FinalStep = 128/iifac;         /* FinalStep=16 */

                while ( worth_a_try && not_decoded && idt<=FinalStep) {
                    ii=(idt+1)/2;
                    if( idt%2 == 1 ) ii=-ii;   /* jika idt ganjil */
                    ii=iifac*ii;
                    jittered_shift=shift1+ii;
		    printf("WAT= %d; ND= %d; idt=%d ii=%d jitter_shift=%d\n\n", 
			   worth_a_try,not_decoded,idt,ii,jittered_shift);
		    //printf("idt=%d ii=%d jitter_shift=%d\n", idt,ii,jittered_shift);

                    t0 = clock();
                    noncoherent_sequence_detection(idat, qdat, npoints, symbols, &f1,
                                    &jittered_shift, &drift1, symfac, &blocksize);

                    tsync2 += (float)(clock()-t0)/CLOCKS_PER_SEC;
		    //                    tsync2 = (float)(clock()-t0)/CLOCKS_PER_SEC;
                
		    /* menghitung nilai RMS  */
                    sq=0.0;
                    for(i=0; i<162; i++) {
                        y=(float)symbols[i] - 128.0;
                        sq += y*y;
                    }
                    rms=sqrt(sq/162.0);
		    /*************************/
		    
		    printf("sync1= %f; minsync2= %f; rms= %f; minrms= %f\n",
			   sync1, minsync2, rms, minrms);
		    
		    /* minrms dan minsync2 ditetapkan oleh desainer */
                    if((sync1 > minsync2) && (rms > minrms)) { /* minsync2=0.12; minrms= 40.6250 */
		      deinterleave(symbols);    // awa-acak untuk indeks simbol
                        t0 = clock();


			char  gambar_symbols[200];
			FILE *fsymbols;
			strcpy(gambar_symbols,"./gambarsymbols.tmp");
			if((fsymbols = fopen(gambar_symbols,"w")) == NULL) {
			  fprintf(stderr, "Cannot open data file '%s'....\n", gambar_symbols);
			  exit(1);
			}

			int iii;
			for(iii=0;iii<162;iii++){
			  fprintf(fsymbols,"%d %u\n", iii, symbols[iii]);
			}    
			fclose(fsymbols);
			iii=0;

			if((gw = popen(GNUPLOT,"w"))==NULL){ /* 'gw' is the pipe descriptor */
			  printf("Error opening pipe to GNU plot. Check if you have it! \n");
			  exit(0);
			}
			fprintf(gw, "plot './gambarsymbols.tmp' lt 1 with impulses title '162 simbol sesudah deinterleave'\n");
			fflush(gw);
			fclose(gw);


			exit(0);     /* PRAKTIKUM-7  */

			/* not_decoded = 0 --> dekode sukses */
			/* not_decoded = -1 --> dekode gagal */
  
  			  not_decoded = fano(&metric,&cycles,&maxnp,decdata,symbols,nbits,
                                           mettab,delta,maxcycles);

			  tfano += (float)(clock()-t0)/CLOCKS_PER_SEC;
                    
		    }
                    idt++;
		}
           
		if( worth_a_try && !not_decoded ) {  // worth_a_try=1 and !not_decoded=1

		  /*  aslinya ada limiter 127 */
		  /*
		  for(i=0; i<11; i++) {
                    if( decdata[i]>127 ) {
		      message[i]=decdata[i]-256;
                    } else {
		      message[i]=decdata[i];
                    }
		  }
		  */
		  /***************************/
		  

		  for(i=0; i<11; i++) {
		      message[i]=decdata[i];
		  }

		  // Unpack the decoded message, update the hashtable, apply
		  // sanity checks on grid and power, and return
		  // call_loc_pow string and also callsign (for de-duping).
		  noprint=unpk_(message,call_loc_pow,callsign);

                // Remove dupes (same callsign and freq within 3 Hz)
                int dupe=0;
                for (i=0; i<uniques; i++) {
                    if(!strcmp(callsign,allcalls[i]) &&
                       (fabs(f1-allfreqs[i]) <3.0)) dupe=1;
                }
                if( !dupe && !noprint) {
		  strcpy(allcalls[uniques],callsign);
		  allfreqs[uniques]=f1;
		  uniques++;
                    
		  // Add an extra space at the end of each line so that wspr-x doesn't
		  // truncate the power (TNX to DL8FCL!)
                    

		  freq_print=dialfreq+(1500+f1)/1e6; //dialfreq == 0
		  dt_print=shift1*dt-1.0;

		  t = time(NULL);
		  tm = *localtime(&t);
		  sprintf(date,"%d:%d:%d", tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday);
		  sprintf(uttime,"%d:%d", tm.tm_hour, tm.tm_min);
		  
		  strcpy(decodes[uniques-1].date,date);
		  strcpy(decodes[uniques-1].time,uttime);
		  decodes[uniques-1].sync=sync1;
		  decodes[uniques-1].snr=snr0[j];
		  decodes[uniques-1].dt=dt_print;
		  decodes[uniques-1].freq=freq_print;
		  strcpy(decodes[uniques-1].message,call_loc_pow);
		  decodes[uniques-1].drift=drift1;
		  decodes[uniques-1].cycles=cycles;
		  decodes[uniques-1].jitter=ii;
		  decodes[uniques-1].blocksize=blocksize;
		  decodes[uniques-1].metric=metric;
		}
		}  // worth a try dan !not decoded

		//jika dekode sukses maka cari kandidat yang lain
	}  // batas j --> npk; jika segala upaya gagal maka cari kandidat lain
        

    // urutkan hasil berdasarkan urutan frekuensi 
    struct result temp;
    for (j = 1; j <= uniques - 1; j++) {
        for (k = 0; k < uniques - j ; k++) {
            if (decodes[k].freq > decodes[k+1].freq) {
                temp = decodes[k];
                decodes[k]=decodes[k+1];;
                decodes[k+1] = temp;
            }
        }
    }
    
    for (i=0; i<uniques; i++) {
      printf("\n%4s %3.0f %4.1f %10.6f %2d  %-s \n",
	     decodes[i].time, decodes[i].snr,decodes[i].dt, decodes[i].freq,
	     (int)decodes[i].drift, decodes[i].message);

        fprintf(fwsprd,
                "%6s %4s %3d %3.0f %4.1f %10.6f  %-22s %2d %5u %4d\n",
                decodes[i].date, decodes[i].time, (int)(10*decodes[i].sync),
                decodes[i].snr, decodes[i].dt, decodes[i].freq,
                decodes[i].message, (int)decodes[i].drift, decodes[i].cycles/81,
                decodes[i].jitter);
        
    }
    printf("<Dekode Paripurna...>\n");
    
    fftwf_free(fftin);
    fftwf_free(fftout);
    
    ttotal += (float)(clock()-t00)/CLOCKS_PER_SEC;
    //    ttotal = (float)(clock()-t00)/CLOCKS_PER_SEC;

    fprintf(ftimer,"%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n\n",
            treadwav,tcandidates,tsync0,tsync1,tsync2,tfano,ttotal);
    
    fprintf(ftimer,"Code segment        Seconds   Frac\n");
    fprintf(ftimer,"-----------------------------------\n");
    fprintf(ftimer,"readwavfile        %7.2f %7.2f\n",treadwav,treadwav/ttotal);
    fprintf(ftimer,"Coarse DT f0 f1    %7.2f %7.2f\n",tcandidates,
            tcandidates/ttotal);
    fprintf(ftimer,"sync_and_demod(0)  %7.2f %7.2f\n",tsync0,tsync0/ttotal);
    fprintf(ftimer,"sync_and_demod(1)  %7.2f %7.2f\n",tsync1,tsync1/ttotal);
    fprintf(ftimer,"sync_and_demod(2)  %7.2f %7.2f\n",tsync2,tsync2/ttotal);
    fprintf(ftimer,"Stack/Fano decoder %7.2f %7.2f\n",tfano,tfano/ttotal);
    fprintf(ftimer,"-----------------------------------\n");
    fprintf(ftimer,"Total              %7.2f %7.2f\n",ttotal,1.0);
    
    //    fclose(fall_wspr);
    fclose(fwsprd);
    fclose(ftimer);
    fclose(gp);
    fftwf_destroy_plan(PLAN1);
    fftwf_destroy_plan(PLAN2);
    fftwf_destroy_plan(PLAN3);
    

   
    //    free(hashtab);
    free(symbols);
    free(decdata);
    free(channel_symbols);
    free(callsign);
    free(call_loc_pow);
    free(idat);
    free(qdat); 

    
    if(writenoise == 999) return -1;  //Silence compiler warning
    return 0;
}


