/*******************************************************************************
 TESINA n°5 per esame di: ELABORAZIONI dei SEGNALI ed INFORMAZIONI di MISURA:

 NOMEFILE: Unit4.cpp (Analizzatore di spettro)

 NOTE: Nel file sono riportate le funzioni relative: all'acquisizione dallo
       Oscilloscopio della forma d'onda visualizzata; alla trasformata di
       Fourier (FFT) dello stesso segnale;alla definizione del tipo di finestra.
*******************************************************************************/

#include <vcl.h>
#pragma hdrstop
#include "Interfaccia.h"           // Header del file, di quelli contenenti i
#include "Unit2.h"                 // prototipi delle classi necessarie, e delle
#include "Unit3.h"                 // funzioni relative alla GPIB
#include "Unit4.h"
#include <stdio.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Fourier"
#pragma link "RChart"
#pragma resource "*.dfm"
TForm4 *Form4;

static int campioni[2500]; // Vettore contenente i campioni da elaborare
static double Ts;          // Periodo di Campionamento
bool   DatiValidi=false;   // Indica la presenza dei campioni nel file'data.dat'
long double FreqMax;       // Variabile usata per memorizzare la frequenza Max
int    start;              // Indica il primo campione da acquisire
int    stop;               // Indica il l'ultimo campione da acquisire

//---------------------------------------------------------------------------
__fastcall TForm4::TForm4(TComponent* Owner) : TForm(Owner) { }
//---------------------------------------------------------------------------

/*******************************************************************************
 La funzione DisegnaFFT istanzia l'oggetto Oscilloscopio, lancia l'acquisizione
 dei dati dallo strumento rilevato ed in fine visualizza la forma d'onda nel
 relativo RChart (ChartFt) sul Pannello acquisizione dati.
*******************************************************************************/
void __fastcall TForm4::DisegnaFFT(TObject *Sender)
{
  TOscilloscopio *Oscilloscopio = new TOscilloscopio;
  Oscilloscopio->Acquisisci();
  DisegnaFt();
}

/*******************************************************************************
 La funzione DisegnaFt legge le informazioni, relative all'onda visualizzata
 sullo Oscilloscopio, dai file "unita.dat" e "data.dat" opportunamente creati
 durante la fase di acquisizione. Una volta lette le informazioni si occupa
 della loro visualizzazione sotto forma di grafico sull'Rchart ChartFt.
*******************************************************************************/
void __fastcall TForm4::DisegnaFt()
{
    int i,j;           // Indici dei cicli for e while
    char c;            // variabile temporanea usata per la lettura del file
    char tmp[10];      // variabile temporanea usata per la lettura del file
    double Ris;        // risoluzione verticale
    char app[10];      // variabile temporanea per le operazioni sulle stringhe
    char misura[10];   // Unita' di misura
    FILE *dati;        // file contenente i campioni del segnale
    FILE *unita;       // file contenente i dati sul campionamento

    // Apertura del file contenente i dati sul campionamento. Se il file non
    // dovesse esistere, o fosse corrotto, un messageBox avvertirà l'utente.
    unita = fopen(".\\unita.dat","r");
    if(unita != NULL)
    {
        fscanf(unita,"%s",app);
        fscanf(unita,"%lf",&Ts);
        fscanf(unita,"%s",app);
        fscanf(unita,"%lf",&Ris);
        fscanf(unita,"%s",app);
        fscanf(unita,"%s",misura);
    }
    else
        MessageBox(NULL,"File dati inesistente","Errore",MB_OK+MB_ICONSTOP);

    // Apertura del file contenente i campioni acquisiti
    dati = fopen(".\\data.dat","r");
    if(dati != NULL)
    {
        DatiValidi = true;                  	// I dati sono presenti nel file
        Form4->ChartFt->ClearGraf();            // Pulitura del grafico
        Form4->ChartFt->DataColor = clBlue;   	// Colore del grafico

        // Il file contiene i campioni in formato carattere separati da virgole.
        // La prima lettura avviene fuori ciclo al fine di eliminare la stringa
        // iniziale inserita dallo strumento per evidenziare il tipo di acquisiz.

        j = 0;             // indice della stringa usata per leggere il campione
        fscanf(dati,"%s",app);
        fscanf(dati,"%c",&c);
        while((c != ',') && (!feof(dati)))
        {
            tmp[j++] = c;           // Si procede alla creazione della stringa
            fscanf(dati,"%c",&c);   // dai caratteri letti passo passo.
        }
        tmp[j] = '\0';    // la stringa costruita viene terminata.
        // la stringa tmp contiene il campione che viene convertito in intero
        campioni[0] = StrToInt(tmp);

        // posizionamento del punto iniziale del grafico
        Form4->ChartFt->MoveTo(0,campioni[0]*Ris);

        // Legge dal form acquisizione il numero di campioni da acquisire
        stop = StrToInt(Form4->EditNumCamp->Text.c_str());

        // Il numero di campioni deve essere almeno 2 e massimo 2500
        if (stop > 2500) stop = 2500 ;
        if (stop < 2)    stop = 2 ;

        // Si leggono dal file i campioni acquisiti e si memorizzano gli stessi
        // in un vettore di interi chiamato "campioni".
        for (i = 1; i < stop-1; i++)
        {
            j = 0;
            fscanf(dati,"%c",&c);
            while((c != ',') && (!feof(dati)))
            {
                tmp[j++] = c;
                fscanf(dati,"%c",&c);
            }
            tmp[j] = '\0';
            campioni[i] = StrToInt(tmp);     // si converte la stringa in intero
            // il campione convertito viene inserito nel grafico
            Form4->ChartFt->DrawTo (i * Ts * 1000,campioni[i]*Ris);
        }
        // a fine operazione il file viene chiuso
        fclose(dati);
        // Definizione dei parametri del grafico:
        // Label dell'asse y (letta dal file 'unita.dat')
        Form4->ChartFt->IdOrdinate = misura;
       	// Label dell'asse x
        Form4->ChartFt->IdAbscissa = "Tempo [ms]";
	// adeguamento del grafico al segnale
        Form4->ChartFt->AutoRange(3);
	// visualizzazione del grafico
        Form4->ChartFt->ShowGraf();
    }
    StartFFT();   // Viene richiamata la funzione per il calcolo della FFT
};

/*******************************************************************************
 La funzione StartFFT porta i campioni acquisiti nel componente FFT1. Calcola
 la trasformata di Fourier, applica la finestra e poi disegna lo spettro scelto.
*******************************************************************************/
void __fastcall TForm4::StartFFT()
{
int    i;               // Variabile usata per i cicli for
double y;               // variabile usata per appoggiare temporaneamente il
                        //    il valore del campione.

// Il primo campione acquisito è il numero '0' e l'ultimo è quello al numero
// corrispondente al valore digitato nell'editBox sul PannelloAcquisizioneDati.
start = 0;
stop  = StrToInt(Form4->EditNumCamp->Text.c_str());

// Il componente FFT1 viene ripulito da eventuali valori precedenti.
FFT1->Clear();

// Si caricano nella parte reale di FFT1 i campioni acquisiti.
for (i=start; i<stop; i++) FFT1->RealSpec[i+1] = campioni[i];

// Si effettua la trasformata di Fourier dei campioni
FFT1->Transform();
// L'Rchart relativo alla FFT viene pulito da eventuali plot precedenti.
FFTChart->ClearGraf();
// Si stabilisce il colore dei punti.
FFTChart->DataColor = clRed;
// Ci si posiziona nel primo punto dello spettro.
FFTChart->MoveTo (FFT1->FreqOfLine(start,Ts),FFT1->Magnitude[start]);
// Si setta la scala verticale dell'RChart di tipo lineare.
FFTChart->LogScaleY = false;

// Viene visualizzata l'opportuna intestazione dell'Rchart a seconda del tipo
// di spettro che si richiede di calcolare. (ampiezza, potenza, fase, ecc)
switch (SceltaSpettro->ItemIndex)
  {
  case 0 : { FFTChart->Caption = "Spettro di Ampiezza";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->Magnitude[start]);
             break;}
  case 1 : { FFTChart->Caption = "Spettro di Potenza";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->PowerSpec[start]);
             break;}
  case 2 : { FFTChart->Caption = "Fase (angolo)";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->Phase[start]);
             break;}
  case 3 : { FFTChart->Caption = "Termini Coseno";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->FourSerCosCoeff[start]);
             break;}
  case 4 : { FFTChart->Caption = "Termini Seno";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->FourSerSinCoeff[start]);
             break;}
  case 5 : { FFTChart->Caption = "Parte reale dello spettro complesso";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->RealSpec[start+1]);
             break;}
  case 6 : { FFTChart->Caption = "Parte immaginaria dello spettro complesso";
             FFTChart->MoveTo(FFT1->FreqOfLine(start,Ts),FFT1->ImagSpec[start+1]);
             break;}
  }

// Si procede alla visualizzazione dello spettro prescelto
for (i=start; i<(stop/StrToInt(Form4->ScrollBar->Position)) ; i++)
  {
  switch (SceltaSpettro->ItemIndex)
    {
    case 0 : y = FFT1->Magnitude[i]; break;
    case 1 : y = FFT1->PowerSpec[i]; break;
    case 2 : y = FFT1->Phase[i]; break;
    case 3 : y = FFT1->FourSerCosCoeff[i];
    case 4 : y = FFT1->FourSerSinCoeff[i];
    case 5 : y = FFT1->RealSpec[i+1]; break;
    case 6 : y = FFT1->ImagSpec[i+1]; break;
    }
  FFTChart->DrawTo (FFT1->FreqOfLine(i,Ts),y);
  }
  FFTChart->ShowGraf();                     // visualizzazione del grafico

FFTChart->IdOrdinate = "Modulo";            // Label dell'asse y
FFTChart->IdAbscissa = "Frequenza [Hz]";    // Label dell'asse x
FFTChart->AutoRange(5);                     // adeguamento del grafico allo spettro
FFTChart->ShowGraf();                       // visualizzazione del grafico

};

/*******************************************************************************
 All'evento Click sul bottone è associata la chiamata alla funzione StartFFT().
*******************************************************************************/
void __fastcall TForm4::DisegnaClick(TObject *Sender)
{
  StartFFT();
}

/*******************************************************************************
 All'evento Change sul comboBox TipoFinestra è associata l'applicazione ai dati
 del tipo di finestra prescelta mediante il metodo WeightingWindow.
*******************************************************************************/
void __fastcall TForm4::TipoFinestraChange(TObject *Sender)
{
 switch (TipoFinestra->ItemIndex)
    {
       case 0: FFT1->WeightingWindow = fwRectangle; break;
       case 1: FFT1->WeightingWindow = fwCos2;      break;
       case 2: FFT1->WeightingWindow = fwHamming;   break;
       case 3: FFT1->WeightingWindow = fwBlackman;  break;
       case 4: FFT1->WeightingWindow = fwTriangle;  break;
    }
    StartFFT();
 ScalaEdit->Text = ScrollBar->Position;
}




