/*************************************************************** 
 *                                                             * 
    File: C.COMMND1

    Inhoud: int QuitCi (char *s), int WriteCi(char *p),int ReadCi(char *p),
            int RenameCi(char *p)

    Schrijvers: Edwin Zoer & Erwin Waterlander
                HTS Enschede
 
   Datum:      juni 1993

 *                                                             * 
 ***************************************************************/ 
 
#include <string.h> 
#include <math.h>
#include <limits.h>
#include <time.h>
#include "window.h" 
#include "bblib.h" 
#include "parse.h" 
#include "commnd.h"
#include "errors.h" 
#include "filetype.h"
 
#define ESC   0x1b 
#define EOS   '\0' 
#define EQUAL 0 

#define PI 3.14159265358979

#define MIN_LENGTH 512

extern void display_signal_plot(VENSTER *vp);
extern void gen_signal_background(VENSTER *vp); 
extern char *GenIm;   /* c.aim */
extern char *Image;   /* c.aim */
extern VENSTER* vp[MAXSIG];
extern unsigned short MAX_LENGTH;
extern unsigned short SAMPLE_RATE;
extern int Find_Signal_Venster(char *signalname);    /* command.c */
extern int Create_Venster(char *signalname,unsigned int alloc_size);         /* command.c */
extern int Realloc_Venster(VENSTER *vp, unsigned int alloc_size);
extern BOOL don;

/*************************************************************************
 * int QuitCi(char *s)                                                   *
 * Einde ASM                                                             *
 *************************************************************************/

int QuitCi (char *s)
{
  visdelay_end();            /* Geen zandloper meer */
  pointer_reset_shape();      
  wimp_exit();               /* command.c  */
  return 0;
}



/*************************************************************************/
 
int HistCi(char *p) 
{ 

 int in_im,out_im,i,j;  /* Vensternummer */
 unsigned int alloc_size,lengte;
 unsigned int offset_in,offset_out;
 unsigned short channel,element;
 int channel_nr,buckets,bucket;
 double Delta;
 char *in_signalname;
 char *out_signalname;
 char buffer1[128],buffer2[128];
 SAMPLE *real_data_out;
 SAMPLE *imag_data_out;
 SAMPLE *real_data_in;
 SAMPLE *imag_data_in;
 SAMPLE *imag_hulp,*real_hulp;    
 BOOL bucket_found;

 in_signalname  = strarg(&p,NULL,"Input Signal","a",buffer1);

 in_im = Find_Signal_Venster(in_signalname);
 if (in_im == -1) return ERR_SIGNAL;       /* Signaal bestaat niet */

 out_signalname = strarg(&p,NULL, "Output Signal",in_signalname,buffer2);

 buckets        = intarg(&p,NULL,"Buckets (2^n)",MIN_N,(int)(log(DataLength(vp[in_im]))/log(2)),(int)(log(DataLength(vp[in_im]))/log(2)));
 channel_nr = (unsigned short) intarg(&p,NULL,"Channel",0,DataChannels(vp[in_im])-1,0);

 if(DataDomain(vp[in_im]) != TIME) return ERR_DOMAIN;

 buckets=pow(2,buckets);
 alloc_size = DataChannels(vp[in_im])*buckets;
 lengte = DataRecords(vp[in_im])*DataLength(vp[in_im]); /* channel lengte */

 out_im = Find_Signal_Venster(out_signalname);      /* Vind het juiste venster */
 if (out_im == -1)                                  /* Signaal bestond nog niet */
 {
  out_im = Create_Venster(out_signalname,alloc_size);
  if (out_im == -1) return ERR_WINDOWS;             /* Te veel displaywindows */
 } 
 else 
   if(in_im != out_im) 
    Realloc_Venster(vp[out_im],alloc_size);

   real_data_out = DataReal(vp[out_im]);    /* Bewaar de pointers voor de data */
   imag_data_out = DataImag(vp[out_im]);
   real_data_in  = DataReal(vp[in_im]);
   imag_data_in  = DataImag(vp[in_im]);


   real_hulp=imag_hulp=NULL;
   real_hulp = (SAMPLE*) heap_alloc((unsigned int)DataAllocSize(vp[in_im])*sizeof(SAMPLE));
   imag_hulp = (SAMPLE*) heap_alloc((unsigned int)DataAllocSize(vp[in_im])*sizeof(SAMPLE));
   if ( (imag_hulp == NULL) || (real_hulp == NULL) )
   werr(1,"Error in HistCi: heap_alloc failed\r");

  /* Copieer de inhoud van de ingangsdata */ 

  for (i=0;i<(DataChannels(vp[in_im])*DataRecords(vp[in_im])*DataLength(vp[in_im]));i++)
   {
     real_hulp[i] = real_data_in[i];
     imag_hulp[i] = imag_data_in[i];
   }

   if (in_im == out_im)
   {
    Realloc_Venster(vp[out_im],alloc_size);
    real_data_in  = real_data_out = DataReal(vp[out_im]);
    imag_data_in  = imag_data_out = DataImag(vp[out_im]);
   }

   (*vp[out_im]).header = (*vp[in_im]).header;   /* Maak de headers aan elkaar gelijk   */
   
   DataReal(vp[out_im]) = real_data_out;             /* Zet de pointers van de data weer terug*/  
   DataImag(vp[out_im]) = imag_data_out;

   DataLength(vp[out_im])=buckets;
   DataRecords(vp[out_im]) = 1;
   DataType(vp[out_im]) = REAL;
   DataDomain(vp[out_im]) = AMPL;
   strncpy(DataSignalName(vp[out_im]),out_signalname,32); 
   Window_Mode(vp[out_im])= HIST_M;
   Window_Record(vp[out_im])= 0;
   Window_Channel(vp[out_im])= channel_nr;

for (channel = 0;channel < DataChannels(vp[in_im]); channel++)
  {                                         
   /* Het histogram wordt per channel van het ingangssignaal bepaalt */
   /* In het histogram gaat het om de magnitude */
   

     /* Bereken de offset van het channel */
     offset_in = channel*lengte;
     offset_out = (channel)*DataRecords(vp[out_im])*DataLength(vp[out_im]);
 
    DataRealMin(vp[out_im])=DataRealMax(vp[out_im])=sqrt(pow(real_hulp[offset_in],2)+pow(imag_hulp[offset_in],2));

     /* Bepaal van de elementen de magnitude en het maximum en minimum */
     for (element=0; element < lengte; element++)
     {
       real_hulp[element+offset_in] = sqrt(pow(real_hulp[element+offset_in],2)+pow(imag_hulp[element+offset_in],2));       
       if (real_hulp[element+offset_in] > DataRealMax(vp[out_im])) 
         DataRealMax(vp[out_im])=real_hulp[element+offset_in];
       if (real_hulp[element+offset_in] < DataRealMin(vp[out_im]))
         DataRealMin(vp[out_im])=real_hulp[element+offset_in];
     }



     Delta=(double)((DataRealMax(vp[out_im])-DataRealMin(vp[out_im]))/(double)(buckets));
    

     /*  Maak de elementen van out_im 0  */
     for(i=0;i<(DataRecords(vp[out_im])*DataLength(vp[out_im]));i++)
      {
       real_data_out[i+offset_out] = 0.0;
       imag_data_out[i+offset_out] = 0.0;
      }                       

       for (i=0;i < lengte;i++)
        {
          bucket = buckets/2;          
          bucket_found = FALSE;

          for(j= (buckets/2);(j>0) && (bucket_found == FALSE);j=(int)(j/2))
          {                                
            
           if ( real_hulp[i+offset_in] >= (DataRealMin(vp[out_im])+((double)bucket+1.0)*Delta))
            bucket = bucket + (int)(j/2);
           else
            { 
             if ( real_hulp[i+offset_in] < (DataRealMin(vp[out_im])+(double)bucket*Delta))
              bucket = bucket - (int)(j/2);
             else
               bucket_found = TRUE;
            }
           if (real_hulp[i+offset_in] < (DataRealMin(vp[out_im])+Delta))
             {
               bucket = 0;
               bucket_found = TRUE;
             }
          }     
          real_data_out[offset_out+bucket] = real_data_out[offset_out+bucket] +1;
         }
      
   }


  heap_free(real_hulp);                         
  heap_free(imag_hulp);
  heap_free(Window_Diag(vp[out_im]).data);
  Window_Diag(vp[out_im]).data = NULL;

  init_plot_draw(vp[out_im]);   

  if (don)
  {
    make_plot(vp[out_im]); 
    display_signal_plot(vp[out_im]);
    Window_InUse(vp[out_im]) = TRUE;
  }
  else
    Window_InUse(vp[out_im]) = FALSE;

 return 0 /*NO_ERROR*/; 
} 




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

int WriteCi(char *p)
{
  extern char signal_dir[];
  char *signalfile;
  int im;
  char *file_name;
  char *user_text;
  char *description;
  char *signalname;
  char buffer1[128],buffer2[128],buffer3[128],buffer4[128];
  short  bps,bitsps;             
  time_t timer;
  char *ctijd;
  
  
 
  signalname = strarg(&p,NULL,"Signal","a",buffer1);
  file_name = strarg(&p,NULL,"Filename",signalname,buffer2); 
  user_text = strarg(&p,NULL,"User Text","",buffer3);
  description = strarg(&p,NULL,"Description","",buffer4);

  im = Find_Signal_Venster(signalname);   /* Vind het juiste venster */
  if (im == -1) return ERR_SIGNAL;        /* Signaal bestaat niet */

  signalfile = (char *) calloc(256,sizeof(char));
  if (signalfile == NULL)
  werr (1,"Error in WriteCi: calloc failed\r");

  strncpy(signalfile,signal_dir,99);
  strncat(signalfile,file_name,10); /* file naam max 10 karakters (RISC OS) */


switch (DataBits_p_s(vp[im]))
  { 
  case BPS_CHAR:      bps=0;break;
  case BPS_SHORT:     bps=1;break;
  case BPS_INT:       bps=2;break;
  case BPS_FLOAT:     bps=3;break;
  case BPS_DOUBLE:    bps=4;break;
  default:            bps=1;break;
  }
  
  bps = (short) intarg(&p,NULL,"BPS 0:char,1:short,2:int,3:float,4:double",0,4,bps);

switch (bps)
  { 
  case 0:      bitsps=BPS_CHAR;break;
  case 1:      bitsps=BPS_SHORT;break;
  case 2:      bitsps=BPS_INT;break;
  case 3:      bitsps=BPS_FLOAT;break;
  case 4:      bitsps=BPS_DOUBLE;break;
  default:     bitsps=BPS_SHORT;break;
  }                        
   user_text[sizeof(DataUserText(vp[im]))-1] = '\0';
   description[sizeof(DataDescription(vp[im]))-1] = '\0';
   signalfile[sizeof(Window_File(vp[im]))-1] = '\0';
  strncpy(DataUserText(vp[im]),user_text,sizeof(DataUserText(vp[im])));
  strncpy(DataDescription(vp[im]),description,sizeof(DataDescription(vp[im])));   
  strncpy(Window_File(vp[im]),signalfile,sizeof(Window_File(vp[im])));
  
  time(&timer);                                     
  ctijd = asctime(localtime(&timer));
  ctijd[sizeof(DataDate(vp[im]))-1] = '\0';
  strncpy(DataDate(vp[im]),ctijd,sizeof(DataDate(vp[im])));

free(signalfile);  
return(todisc(vp[im],ASMF,bitsps));
  
}

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

int ReadCi(char *p)
{
  extern char signal_dir[];
  int im;
  int filetype;
  char *signalfile;
  unsigned int alloc_size;
  char *file_name;
  char *signalname;
  char buffer1[128],buffer2[128];
  FILE *fp;
  
  file_name  = strarg(&p,NULL,"Filename","a",buffer1); 
  signalname = strarg(&p,NULL,"Signal",file_name,buffer2);

  signalfile = (char *) calloc(256,sizeof(char));
  if (signalfile == NULL)
  werr (1,"Error in ReadCi: calloc failed\r");

  strncpy(signalfile,signal_dir,99);
  strncat(signalfile,file_name,10); /* file naam max 10 karakters (RISC OS)*/


/* Controleer of de file wel bestaat */
  
if((fp=fopen(signalfile,"rb"))==NULL)
   { 
   fclose(fp);
   return(ERR_OPENFILE);
   }  
fclose(fp);    /* Sluit de file, als hij bestond */

  GetFileType(signalfile,&filetype);
  

  if ( !((filetype == ASMF) || (filetype == TCL)) )
    return   ERR_FILETYPE;


 /* Neem een voorlopige alloc_size, er moet nog gerealloceerd worden
    omdat de grootte nu nog niet bekend is.                  */

 alloc_size = 128; /* willekeurig */

 im = Find_Signal_Venster(signalname);   /* Vind het juiste venster */
 if (im == -1)                           /* Signaal bestond nog niet */
  {
   im = Create_Venster(signalname,alloc_size);
   if (im == -1) return ERR_WINDOWS;      /* Te veel displaywindows */
  } 
else Realloc_Venster(vp[im],alloc_size);


  signalfile[sizeof(Window_File(vp[im]))-1] = '\0';
  strncpy(Window_File(vp[im]),signalfile,sizeof(Window_File(vp[im])));
  if (fromdisc(vp[im],filetype)==ERR_OPENFILE)
  return ERR_OPENFILE;
  signalname[sizeof(DataSignalName(vp[im]))-1] = '\0';
  strncpy(DataSignalName(vp[im]),signalname,sizeof(DataSignalName(vp[im])));
  Window_Record(vp[im]) = 0;     /* Te displayen record */
  Window_Channel(vp[im]) =0;     /* Te displayen channel */

  switch(DataDomain(vp[im]))
  {
   case TIME: Window_Mode(vp[im]) = REAL_M;
              break;
   case FREQ: Window_Mode(vp[im]) = BODE_M;
              break;
   case AMPL: Window_Mode(vp[im]) = HIST_M;
              break;
   case MAGN: Window_Mode(vp[im]) = MAGN_M;
              break;
   case PHAS: Window_Mode(vp[im]) = PHAS_M;
              break;                    
   default:   Window_Mode(vp[im]) = REAL_M;
              break;
  }
   



  free(signalfile);
  heap_free(Window_Diag(vp[im]).data);
  Window_Diag(vp[im]).data=NULL;
  init_plot_draw(vp[im]);


if (don)
  {  
  make_plot(vp[im]);
  display_signal_plot(vp[im]);
  
  Window_InUse(vp[im]) = TRUE;
  }
else
    Window_InUse(vp[im]) = FALSE;
return 0;         /* No Error */
}
 
                                

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

int RenameCi(char *p)
{
  int im;
  char buffer1[128],buffer2[128];
  char *in_signalname;
  char *out_signalname;
  char nm[128];
 
  in_signalname  = strarg(&p,NULL,"Signal","a",buffer1);
  out_signalname = strarg(&p,NULL,"Name","b",buffer2);

  im = Find_Signal_Venster(in_signalname);
  if (im == -1) return ERR_SIGNAL;       /* Signaal bestaat niet */

  if (Find_Signal_Venster(out_signalname) != (-1) )
    return ERR_EXIST;         /* Signaal bestaat al */
    


  strncpy(DataSignalName(vp[im]),out_signalname,sizeof(DataSignalName(vp[im])));

  switch (Window_Mode(vp[im]))
  {
  case REAL_M:strncpy(nm,"Signal ",10);
              strncat(nm,DataSignalName(vp[im]),40);
              if (DataDomain(vp[im])==TIME)
                strncat(nm,"  Real (Time)",20);
              if (DataDomain(vp[im])==FREQ)
                strncat(nm,"  Real (Freq)",20);
              break;
  case IMAG_M:strncpy(nm,"Signal ",10);
              strncat(nm,DataSignalName(vp[im]),40);
              if (DataDomain(vp[im])==TIME)  
                strncat(nm,"  Imaginary (Time)",20);
              if (DataDomain(vp[im])==FREQ)
                strncat(nm,"  Imaginary (Freq)",20);
              break;
  case BODE_M:strncpy(nm,"Signal ",10);
              strncat(nm,DataSignalName(vp[im]),40);
              strncat(nm,"  BodeDiagram",20);
              break;
  case PHAS_M:strncpy(nm,"Signal ",10);
              strncat(nm,DataSignalName(vp[im]),40);
              strncat(nm,"  Phase",20);           
              break;
  case MAGN_M:strncpy(nm,"Signal ",10);  
              strncat(nm,DataSignalName(vp[im]),40);
              strncat(nm,"  Magnitude",20);
              break;
  default    :break;
  }

  win_settitle(Window_Handle(vp[im]),nm);
  return 0;
}
