clear;
clc;
close all;

% ============================================================
% GX-TXT-v3
% Analisi dinamica HOLD -> LED
%
% VERSIONE 6
%
% CH2 = V_HOLD
% CH3 = N_LED_ARANCIO
%
% Oltre all'analisi della V5 questa versione salva:
%
% - metadati della prova
% - risultati della singola acquisizione
% - tabella completa della scarica HOLD
% - una riga nel database CSV cumulativo
% - tutti i grafici PNG
%
% ============================================================


% ============================================================
% METADATI DELLA PROVA
%
% QUESTO E' IL BLOCCO DA MODIFICARE AD OGNI MISURA
% ============================================================

filename = 'time_led.csv';

testID = 'burst100_vgen305_gain5_sens9432';

RGAIN_ohm = 5.0;
RSENS_ohm = 9432.0;

frequenza_Hz = 38000;
numeroImpulsi = 100;

% Ampiezza impostata sul generatore
VGEN_V = 3.05;

dutyCycle_pct = 50.0;

% Fotocorrente stimata dalla precedente caratterizzazione
% del fotodiodo virtuale.
%
% Lasciare NaN se non ancora calcolata.
IPD_uA = NaN;

modalitaStimolo = 'burst';

% Il tempo LED viene riferito a t = 0,
% che in queste acquisizioni coincide con l'inizio del burst.
triggerReference = 'burst_start';


% ============================================================
% CARTELLE E FILE DI OUTPUT
% ============================================================

outputRoot = 'calibrazione script';

% Ogni prova viene salvata in una propria sottocartella
outputDir = fullfile(outputRoot, testID);

% Database cumulativo di tutte le prove
cumulativeCSV = fullfile( ...
    outputRoot, ...
    'GXTXT_risultati_completi.csv');

% Risoluzione grafici
pngDPI = 200;


% ============================================================
% PARAMETRI ELETTRICI
% ============================================================

RLED = 680;                % ohm


% ============================================================
% PARAMETRI FIT HOLD
% ============================================================

deltaVHold = 0.10;         % V

holdFitMargin = 0.30;      % V


% ============================================================
% PARAMETRI DERIVATA LED
%
% Questi parametri costituiscono parte del metodo di analisi
% e vanno mantenuti costanti nei confronti tra misure.
% ============================================================

ledBin_ms = 1.0;

ledSlopeWindow_ms = 50.0;

% Validato sul dataset di calibrazione
ledPeakFraction = 0.10;

ledNoiseSigma = 5.0;

ledStable_ms = 30.0;

ledPlotMargin = 0.35;      % s


% ============================================================
% PARAMETRI DERIVATA HOLD - SCARICA LENTA
% ============================================================

holdSlowBin_ms = 5.0;

holdSlowSlopeWindow_ms = 100.0;

holdDischargeDelay = 0.050;   % s


% ============================================================
% PARAMETRI DERIVATA HOLD - CARICA RAPIDA
% ============================================================

holdFastBin_ms = 0.10;

holdFastSlopeWindow_ms = 0.50;

holdFastPre_ms  = 5;
holdFastPost_ms = 15;


% ============================================================
% GRANDEZZE DERIVATE DAI METADATI
% ============================================================

durataBurst_s = numeroImpulsi / frequenza_Hz;
durataBurst_ms = durataBurst_s * 1000;

timestamp = strftime( ...
    '%Y-%m-%d %H:%M:%S', ...
    localtime(time()));


% ============================================================
% CREAZIONE CARTELLE
% ============================================================

if (exist(outputRoot, 'dir') != 7)
    mkdir(outputRoot);
endif

if (exist(outputDir, 'dir') != 7)
    mkdir(outputDir);
endif


% ============================================================
% LETTURA HEADER CSV RIGOL
% ============================================================

fid = fopen(filename, 'r');

if (fid < 0)
    error('Impossibile aprire il file %s', filename);
endif

riga1 = fgetl(fid);
riga2 = fgetl(fid);

campi = strsplit(riga2, ',');

tStart = str2double(campi{4});
dt     = str2double(campi{5});

if (isnan(tStart) || isnan(dt))

    fclose(fid);

    error( ...
        'Impossibile ricavare Start o Increment dall''header.');

endif


% ============================================================
% LETTURA DATI
%
% Rigol:
%
% Sequence,CH2,CH3,
%
% La virgola finale viene consumata esplicitamente.
% ============================================================

dati = fscanf( ...
    fid, ...
    '%f,%f,%f,', ...
    [3, Inf])';

fclose(fid);

if (isempty(dati))
    error('Nessun dato letto dal CSV.');
endif

if (size(dati,2) != 3)
    error('Numero di colonne inatteso.');
endif


seq   = dati(:,1);
vHold = dati(:,2);
vLed  = dati(:,3);

t = tStart + seq .* dt;

N = length(t);


% ============================================================
% CONTROLLO LETTURA
% ============================================================

printf('\n');
printf('============================================================\n');
printf('GX-TXT-v3 - ANALISI HOLD / LED - VERSIONE 6\n');
printf('============================================================\n\n');

printf('Test ID                   : %s\n', testID);
printf('CSV                       : %s\n', filename);

printf('\n');

printf('Prime 10 righe:\n\n');

printf(' Sequence       tempo [s]     V_HOLD [V]     N_LED [V]\n');
printf('------------------------------------------------------------\n');

for k = 1:min(10,N)

    printf('%8d      %10.6f      %8.3f      %8.3f\n', ...
           seq(k), ...
           t(k), ...
           vHold(k), ...
           vLed(k));

endfor

printf('\n');

printf('Campioni                  : %d\n', N);
printf('Start                     : %.6f s\n', tStart);
printf('dt                        : %.3f us\n', dt*1e6);
printf('Fs                        : %.3f kS/s\n', 1/dt/1000);

printf('\n');

printf('V_HOLD min                : %.3f V\n', min(vHold));
printf('V_HOLD max                : %.3f V\n', max(vHold));
printf('N_LED min                 : %.3f V\n', min(vLed));
printf('N_LED max                 : %.3f V\n', max(vLed));


% ============================================================
% BASELINE AUTOMATICHE DAL PRETRIGGER
% ============================================================

idxPre = find(t < -0.1);

if (isempty(idxPre))

    idxPre = ...
        1:max(100,round(0.05*N));

endif

VholdBase = median(vHold(idxPre));
VCC       = median(vLed(idxPre));


% ============================================================
% CORRENTE LED
% ============================================================

iLed = ...
    (VCC-vLed) ./ RLED;

iLed(iLed < 0) = 0;

iLed_mA = ...
    iLed .* 1000;


% ============================================================
% MASSIMI
% ============================================================

[VholdMax, idxHoldMax] = ...
    max(vHold);

tHoldMax = ...
    t(idxHoldMax);


[IledMax, idxIledMax] = ...
    max(iLed_mA);

tIledMax = ...
    t(idxIledMax);


% ============================================================
% TABELLA AUTOMATICA SCARICA HOLD
% ============================================================

vTop = ...
    floor(VholdMax/deltaVHold)*deltaVHold;

vBottom = ...
    ceil( ...
        (VholdBase+holdFitMargin)/deltaVHold ...
    )*deltaVHold;

livelliHold = ...
    (vTop:-deltaVHold:vBottom)';

nLivelli = ...
    length(livelliHold);

tabTempo = NaN(nLivelli,1);
tabVled  = NaN(nLivelli,1);
tabIled  = NaN(nLivelli,1);


for k = 1:nLivelli

    target = livelliHold(k);

    idxRel = find( ...
        vHold(idxHoldMax:end) <= target, ...
        1, ...
        'first');

    if (isempty(idxRel))
        continue;
    endif


    idx = ...
        idxHoldMax + idxRel - 1;


    if (idx <= idxHoldMax)

        tcross = t(idx);

    else

        v1 = vHold(idx-1);
        v2 = vHold(idx);

        t1 = t(idx-1);
        t2 = t(idx);

        if (abs(v2-v1) < eps)

            tcross = t2;

        else

            tcross = ...
                t1 + ...
                (target-v1) * ...
                (t2-t1) / ...
                (v2-v1);

        endif

    endif


    tabTempo(k) = tcross;


    tabVled(k) = interp1( ...
        t, ...
        vLed, ...
        tcross, ...
        'linear');


    tabIled(k) = ...
        1000 * ...
        (VCC-tabVled(k)) / ...
        RLED;


    if (tabIled(k) < 0)
        tabIled(k) = 0;
    endif

endfor


valid = ...
    !isnan(tabTempo);

livelliHold = livelliHold(valid);
tabTempo    = tabTempo(valid);
tabVled     = tabVled(valid);
tabIled     = tabIled(valid);


% ============================================================
% FIT ESPONENZIALE HOLD
%
% V(t) = Vbase + A exp(-(t-t0)/tau)
% ============================================================

tFitHold = ...
    tabTempo - tHoldMax;

vFitHold = ...
    livelliHold - VholdBase;

validFit = ...
    vFitHold > holdFitMargin;

xFit = ...
    tFitHold(validFit);

yFit = ...
    log(vFitHold(validFit));


if (length(xFit) < 3)

    error( ...
        'Troppi pochi punti disponibili per il fit HOLD.');

endif


pHold = ...
    polyfit(xFit,yFit,1);

tauHold = ...
    -1/pHold(1);

AHold = ...
    exp(pHold(2));


% ============================================================
% R^2 FIT HOLD
% ============================================================

vHoldPred = ...
    VholdBase + ...
    AHold .* ...
    exp(-xFit./tauHold);

vHoldMis = ...
    livelliHold(validFit);

SSres = ...
    sum((vHoldMis-vHoldPred).^2);

SStot = ...
    sum((vHoldMis-mean(vHoldMis)).^2);

R2hold = ...
    1-SSres/SStot;


% ============================================================
% CAPACITA' APPARENTE
%
% NON e' una misura diretta del tantalio.
% ============================================================

RholdNominale = 100e3;

Capp = ...
    tauHold/RholdNominale;

Capp_uF = ...
    Capp*1e6;


% ============================================================
% PREELABORAZIONE DERIVATA LED
% ============================================================

nBinLed = max( ...
    1, ...
    round((ledBin_ms/1000)/dt));

nBlocchiLed = ...
    floor(N/nBinLed);

nUsatiLed = ...
    nBlocchiLed*nBinLed;

tLedTmp = ...
    t(1:nUsatiLed);

vLedTmp = ...
    vLed(1:nUsatiLed);


tLedB = mean( ...
    reshape( ...
        tLedTmp, ...
        nBinLed, ...
        nBlocchiLed), ...
    1)';

vLedB = mean( ...
    reshape( ...
        vLedTmp, ...
        nBinLed, ...
        nBlocchiLed), ...
    1)';

dtLedB = ...
    median(diff(tLedB));


% ============================================================
% DERIVATA LOCALE LED
% ============================================================

nWinLed = round( ...
    (ledSlopeWindow_ms/1000) / ...
    dtLedB);

if (nWinLed < 3)
    nWinLed = 3;
endif

if (mod(nWinLed,2) == 0)
    nWinLed = nWinLed+1;
endif

halfWinLed = ...
    floor(nWinLed/2);

xLedLocal = ...
    (-halfWinLed:halfWinLed)' .* ...
    dtLedB;

denLedSlope = ...
    sum(xLedLocal.^2);

kernelLedSlope = ...
    flipud(xLedLocal) ./ ...
    denLedSlope;

dVled_dt = conv( ...
    vLedB, ...
    kernelLedSlope, ...
    'valid');

tLedSlope = ...
    tLedB( ...
        halfWinLed+1 : ...
        end-halfWinLed);


% ============================================================
% MASSIMO DEL LOBO PRINCIPALE LED
% ============================================================

idxLedPost = find( ...
    tLedSlope > tHoldMax);

if (isempty(idxLedPost))

    error( ...
        'Nessun dato LED disponibile dopo la carica HOLD.');

endif


[dLedMax,idxRel] = ...
    max(dVled_dt(idxLedPost));

idxLedPeak = ...
    idxLedPost(idxRel);

tLedPeak = ...
    tLedSlope(idxLedPeak);


% ============================================================
% FONDO DELLA DERIVATA
% ============================================================

tBaseStart = ...
    tHoldMax + 0.050;

tBaseEnd = ...
    tHoldMax + ...
    0.60*(tLedPeak-tHoldMax);

idxLedBase = find( ...
    tLedSlope >= tBaseStart & ...
    tLedSlope <= tBaseEnd);


if (length(idxLedBase) < 10)

    idxLedBase = find( ...
        tLedSlope > tHoldMax & ...
        tLedSlope < tLedPeak);

endif


dLedBase = ...
    dVled_dt(idxLedBase);

muLedBase = ...
    median(dLedBase);

MADled = ...
    median( ...
        abs(dLedBase-muLedBase));

sigmaLedBase = ...
    1.4826*MADled;


if (sigmaLedBase <= eps)
    sigmaLedBase = std(dLedBase);
endif


% ============================================================
% SOGLIA DEL LOBO LED
% ============================================================

thresholdNoise = ...
    muLedBase + ...
    ledNoiseSigma*sigmaLedBase;

thresholdPeak = ...
    ledPeakFraction*dLedMax;

thresholdLed = ...
    max([ ...
        0 ...
        thresholdNoise ...
        thresholdPeak ...
    ]);


% ============================================================
% DURATA MINIMA DI STABILITA'
% ============================================================

dtLedSlope = ...
    median(diff(tLedSlope));

nStableLed = max( ...
    1, ...
    round( ...
        (ledStable_ms/1000) / ...
        dtLedSlope));


% ============================================================
% INIZIO DEL LOBO PRINCIPALE
% ============================================================

idxLedStart = 1;

startFound = false;


for i = idxLedPeak-1:-1:nStableLed

    j1 = ...
        i-nStableLed+1;

    j2 = i;

    if (all( ...
        dVled_dt(j1:j2) <= thresholdLed))

        idxLedStart = i+1;

        startFound = true;

        break;

    endif

endfor


if (!startFound)

    idxTmp = find( ...
        dVled_dt(1:idxLedPeak) <= thresholdLed, ...
        1, ...
        'last');

    if (!isempty(idxTmp))
        idxLedStart = idxTmp+1;
    endif

endif


% ============================================================
% FINE DEL LOBO PRINCIPALE
% ============================================================

idxLedEnd = ...
    length(dVled_dt);

endFound = false;


for i = ...
        idxLedPeak+1 : ...
        length(dVled_dt)-nStableLed+1

    j1 = i;

    j2 = ...
        i+nStableLed-1;

    if (all( ...
        dVled_dt(j1:j2) <= thresholdLed))

        idxLedEnd = i-1;

        endFound = true;

        break;

    endif

endfor


% ============================================================
% TEMPI TRANSIZIONE LED
% ============================================================

tLedStart = ...
    tLedSlope(idxLedStart);

tLedEnd = ...
    tLedSlope(idxLedEnd);

transitionTime = ...
    tLedEnd-tLedStart;

transitionTime_ms = ...
    transitionTime*1000;


% ============================================================
% TEMPO DI ACCENSIONE LED
%
% t = 0 coincide con l'inizio del burst.
%
% Questa grandezza sara' particolarmente utile per i
% confronti futuri:
%
% t_LED = f(VGEN)
% t_LED = f(IPD)
% t_LED = f(RGAIN)
% ecc.
% ============================================================

tempoLedAcceso_s = ...
    tLedEnd;

tempoLedAcceso_ms = ...
    tempoLedAcceso_s*1000;


% ============================================================
% GRANDEZZE NEI TRE PUNTI DELLA TRANSIZIONE
% ============================================================

VholdLedStart = interp1( ...
    t, ...
    vHold, ...
    tLedStart, ...
    'linear');

VholdLedPeak = interp1( ...
    t, ...
    vHold, ...
    tLedPeak, ...
    'linear');

VholdLedEnd = interp1( ...
    t, ...
    vHold, ...
    tLedEnd, ...
    'linear');


VledStart = interp1( ...
    t, ...
    vLed, ...
    tLedStart, ...
    'linear');

VledPeak = interp1( ...
    t, ...
    vLed, ...
    tLedPeak, ...
    'linear');

VledEnd = interp1( ...
    t, ...
    vLed, ...
    tLedEnd, ...
    'linear');


IledStart = max( ...
    0, ...
    1000*(VCC-VledStart)/RLED);

IledPeak = max( ...
    0, ...
    1000*(VCC-VledPeak)/RLED);

IledEnd = max( ...
    0, ...
    1000*(VCC-VledEnd)/RLED);


% ============================================================
% HOLD - DERIVATA RAPIDA DELLA CARICA
% ============================================================

nBinHF = max( ...
    1, ...
    round((holdFastBin_ms/1000)/dt));

nBlocchiHF = ...
    floor(N/nBinHF);

nUsatiHF = ...
    nBlocchiHF*nBinHF;

tHFTmp = ...
    t(1:nUsatiHF);

vHFTmp = ...
    vHold(1:nUsatiHF);


tHFB = mean( ...
    reshape( ...
        tHFTmp, ...
        nBinHF, ...
        nBlocchiHF), ...
    1)';

vHFB = mean( ...
    reshape( ...
        vHFTmp, ...
        nBinHF, ...
        nBlocchiHF), ...
    1)';

dtHFB = ...
    median(diff(tHFB));


nWinHF = round( ...
    (holdFastSlopeWindow_ms/1000) / ...
    dtHFB);

if (nWinHF < 3)
    nWinHF = 3;
endif

if (mod(nWinHF,2) == 0)
    nWinHF = nWinHF+1;
endif

halfWinHF = ...
    floor(nWinHF/2);

xHF = ...
    (-halfWinHF:halfWinHF)' .* ...
    dtHFB;

kernelHF = ...
    flipud(xHF) ./ ...
    sum(xHF.^2);

dVholdFast_dt = conv( ...
    vHFB, ...
    kernelHF, ...
    'valid');

tHoldFastSlope = ...
    tHFB( ...
        halfWinHF+1 : ...
        end-halfWinHF);


% ============================================================
% HOLD - DERIVATA LENTA DELLA SCARICA
% ============================================================

nBinHS = max( ...
    1, ...
    round((holdSlowBin_ms/1000)/dt));

nBlocchiHS = ...
    floor(N/nBinHS);

nUsatiHS = ...
    nBlocchiHS*nBinHS;

tHSTmp = ...
    t(1:nUsatiHS);

vHSTmp = ...
    vHold(1:nUsatiHS);


tHSB = mean( ...
    reshape( ...
        tHSTmp, ...
        nBinHS, ...
        nBlocchiHS), ...
    1)';

vHSB = mean( ...
    reshape( ...
        vHSTmp, ...
        nBinHS, ...
        nBlocchiHS), ...
    1)';

dtHSB = ...
    median(diff(tHSB));


nWinHS = round( ...
    (holdSlowSlopeWindow_ms/1000) / ...
    dtHSB);

if (nWinHS < 3)
    nWinHS = 3;
endif

if (mod(nWinHS,2) == 0)
    nWinHS = nWinHS+1;
endif

halfWinHS = ...
    floor(nWinHS/2);

xHS = ...
    (-halfWinHS:halfWinHS)' .* ...
    dtHSB;

kernelHS = ...
    flipud(xHS) ./ ...
    sum(xHS.^2);

dVholdSlow_dt = conv( ...
    vHSB, ...
    kernelHS, ...
    'valid');

tHoldSlowSlope = ...
    tHSB( ...
        halfWinHS+1 : ...
        end-halfWinHS);


% ============================================================
% OUTPUT A VIDEO
% ============================================================

printf('\n');
printf('============================================================\n');
printf('RISULTATI GENERALI\n');
printf('============================================================\n\n');

printf('Baseline HOLD            : %.4f V\n', VholdBase);
printf('VCC stimata              : %.4f V\n', VCC);

printf('\n');

printf('V_HOLD max               : %.4f V\n', VholdMax);
printf('Tempo V_HOLD max         : %.6f s\n', tHoldMax);

printf('\n');

printf('I_LED max                : %.4f mA\n', IledMax);
printf('Tempo I_LED max          : %.6f s\n', tIledMax);


printf('\n');
printf('============================================================\n');
printf('FIT SCARICA HOLD\n');
printf('============================================================\n\n');

printf('Tau HOLD                 : %.4f s\n', tauHold);
printf('R^2                      : %.6f\n', R2hold);

printf('C apparente con 100 kOhm : %.3f uF\n', ...
       Capp_uF);


printf('\n');
printf('============================================================\n');
printf('RICONOSCIMENTO AUTOMATICO SPEGNIMENTO LED\n');
printf('============================================================\n\n');

printf('Soglia %% massimo         : %.2f %%\n', ...
       ledPeakFraction*100);

printf('Massima derivata         : %.4f V/s\n', ...
       dLedMax);


printf('\n');
printf('--- INIZIO TRANSIZIONE ---\n');

printf('Tempo                    : %.6f s\n', ...
       tLedStart);

printf('V_HOLD                   : %.4f V\n', ...
       VholdLedStart);

printf('N_LED                    : %.4f V\n', ...
       VledStart);

printf('I_LED                    : %.4f mA\n', ...
       IledStart);


printf('\n');
printf('--- MASSIMA VELOCITA ---\n');

printf('Tempo                    : %.6f s\n', ...
       tLedPeak);

printf('V_HOLD                   : %.4f V\n', ...
       VholdLedPeak);

printf('N_LED                    : %.4f V\n', ...
       VledPeak);

printf('I_LED                    : %.4f mA\n', ...
       IledPeak);

printf('dV_LED/dt                : %.4f V/s\n', ...
       dLedMax);


printf('\n');
printf('--- FINE TRANSIZIONE ---\n');

printf('Tempo                    : %.6f s\n', ...
       tLedEnd);

printf('V_HOLD                   : %.4f V\n', ...
       VholdLedEnd);

printf('N_LED                    : %.4f V\n', ...
       VledEnd);

printf('I_LED                    : %.4f mA\n', ...
       IledEnd);


printf('\n');

printf('Durata transizione       : %.3f ms\n', ...
       transitionTime_ms);

printf('Tempo LED acceso         : %.6f s\n', ...
       tempoLedAcceso_s);


% ============================================================
% SALVATAGGIO METADATI.TXT
% ============================================================

metadataFile = ...
    fullfile(outputDir,'metadati.txt');

fidMeta = ...
    fopen(metadataFile,'w');


fprintf(fidMeta, ...
    'GX-TXT-v3 - METADATI DELLA PROVA\n');

fprintf(fidMeta, ...
    '============================================\n\n');

fprintf(fidMeta, ...
    'Timestamp: %s\n', ...
    timestamp);

fprintf(fidMeta, ...
    'Test ID: %s\n', ...
    testID);

fprintf(fidMeta, ...
    'CSV sorgente: %s\n', ...
    filename);

fprintf(fidMeta, ...
    'Modalita stimolo: %s\n', ...
    modalitaStimolo);

fprintf(fidMeta, ...
    'Riferimento trigger: %s\n', ...
    triggerReference);

fprintf(fidMeta, ...
    '\n');


fprintf(fidMeta, ...
    'RGAIN = %.6f ohm\n', ...
    RGAIN_ohm);

fprintf(fidMeta, ...
    'RSENS = %.6f ohm\n', ...
    RSENS_ohm);

fprintf(fidMeta, ...
    'Frequenza = %.6f Hz\n', ...
    frequenza_Hz);

fprintf(fidMeta, ...
    'Numero impulsi = %d\n', ...
    numeroImpulsi);

fprintf(fidMeta, ...
    'Durata burst = %.6f ms\n', ...
    durataBurst_ms);

fprintf(fidMeta, ...
    'VGEN = %.6f V\n', ...
    VGEN_V);

fprintf(fidMeta, ...
    'Duty cycle = %.3f %%\n', ...
    dutyCycle_pct);

fprintf(fidMeta, ...
    'IPD stimata = %.6f uA\n', ...
    IPD_uA);

fprintf(fidMeta, ...
    'RLED = %.3f ohm\n', ...
    RLED);


fprintf(fidMeta, ...
    '\nPARAMETRI ACQUISIZIONE\n');

fprintf(fidMeta, ...
    '--------------------------------------------\n');

fprintf(fidMeta, ...
    'Campioni = %d\n', ...
    N);

fprintf(fidMeta, ...
    'Start = %.9f s\n', ...
    tStart);

fprintf(fidMeta, ...
    'dt = %.12f s\n', ...
    dt);

fprintf(fidMeta, ...
    'Fs = %.6f Sa/s\n', ...
    1/dt);


fprintf(fidMeta, ...
    '\nPARAMETRI ANALISI\n');

fprintf(fidMeta, ...
    '--------------------------------------------\n');

fprintf(fidMeta, ...
    'deltaVHold = %.6f V\n', ...
    deltaVHold);

fprintf(fidMeta, ...
    'holdFitMargin = %.6f V\n', ...
    holdFitMargin);

fprintf(fidMeta, ...
    'ledBin = %.6f ms\n', ...
    ledBin_ms);

fprintf(fidMeta, ...
    'ledSlopeWindow = %.6f ms\n', ...
    ledSlopeWindow_ms);

fprintf(fidMeta, ...
    'ledPeakFraction = %.6f\n', ...
    ledPeakFraction);

fprintf(fidMeta, ...
    'ledStable = %.6f ms\n', ...
    ledStable_ms);

fclose(fidMeta);


% ============================================================
% SALVATAGGIO RISULTATI.TXT
%
% Contiene:
%
% - risultati principali
% - tabella transizione LED
% - tabella completa scarica HOLD
% ============================================================

resultsTXT = ...
    fullfile(outputDir,'risultati.txt');

fidTXT = ...
    fopen(resultsTXT,'w');


fprintf(fidTXT, ...
    'GX-TXT-v3 - RISULTATI ANALISI\n');

fprintf(fidTXT, ...
    '============================================\n\n');

fprintf(fidTXT, ...
    'Test ID: %s\n', ...
    testID);

fprintf(fidTXT, ...
    'Timestamp: %s\n\n', ...
    timestamp);


fprintf(fidTXT, ...
    'RISULTATI GENERALI\n');

fprintf(fidTXT, ...
    '--------------------------------------------\n');

fprintf(fidTXT, ...
    'Baseline HOLD         : %.4f V\n', ...
    VholdBase);

fprintf(fidTXT, ...
    'VCC                   : %.4f V\n', ...
    VCC);

fprintf(fidTXT, ...
    'V_HOLD max            : %.4f V\n', ...
    VholdMax);

fprintf(fidTXT, ...
    'Tempo V_HOLD max      : %.6f s\n', ...
    tHoldMax);

fprintf(fidTXT, ...
    'I_LED max             : %.4f mA\n', ...
    IledMax);

fprintf(fidTXT, ...
    'Tempo I_LED max       : %.6f s\n', ...
    tIledMax);


fprintf(fidTXT, ...
    '\nFIT SCARICA HOLD\n');

fprintf(fidTXT, ...
    '--------------------------------------------\n');

fprintf(fidTXT, ...
    'Tau HOLD              : %.6f s\n', ...
    tauHold);

fprintf(fidTXT, ...
    'R^2                   : %.6f\n', ...
    R2hold);

fprintf(fidTXT, ...
    'C apparente 100 kOhm  : %.6f uF\n', ...
    Capp_uF);


fprintf(fidTXT, ...
    '\nTRANSIZIONE LED\n');

fprintf(fidTXT, ...
    '--------------------------------------------\n');

fprintf(fidTXT, ...
    'Durata transizione    : %.3f ms\n', ...
    transitionTime_ms);

fprintf(fidTXT, ...
    'Tempo LED acceso      : %.6f s\n', ...
    tempoLedAcceso_s);

fprintf(fidTXT, ...
    'Massima dV_LED/dt     : %.6f V/s\n', ...
    dLedMax);


fprintf(fidTXT, ...
    '\n');

fprintf(fidTXT, ...
    '%-22s %12s %12s %12s %12s\n', ...
    'Punto', ...
    'Tempo[s]', ...
    'HOLD[V]', ...
    'N_LED[V]', ...
    'I_LED[mA]');

fprintf(fidTXT, ...
    '----------------------------------------------------------------------\n');

fprintf(fidTXT, ...
    '%-22s %12.6f %12.4f %12.4f %12.4f\n', ...
    'Inizio transizione', ...
    tLedStart, ...
    VholdLedStart, ...
    VledStart, ...
    IledStart);

fprintf(fidTXT, ...
    '%-22s %12.6f %12.4f %12.4f %12.4f\n', ...
    'Massima pendenza', ...
    tLedPeak, ...
    VholdLedPeak, ...
    VledPeak, ...
    IledPeak);

fprintf(fidTXT, ...
    '%-22s %12.6f %12.4f %12.4f %12.4f\n', ...
    'Fine transizione', ...
    tLedEnd, ...
    VholdLedEnd, ...
    VledEnd, ...
    IledEnd);


fprintf(fidTXT, ...
    '\n\nTABELLA SCARICA HOLD\n');

fprintf(fidTXT, ...
    '--------------------------------------------\n');

fprintf(fidTXT, ...
    '%12s %12s %12s %12s\n', ...
    'HOLD[V]', ...
    'Tempo[s]', ...
    'N_LED[V]', ...
    'I_LED[mA]');

fprintf(fidTXT, ...
    '-------------------------------------------------------\n');


for k = 1:length(livelliHold)

    fprintf(fidTXT, ...
        '%12.3f %12.6f %12.3f %12.3f\n', ...
        livelliHold(k), ...
        tabTempo(k), ...
        tabVled(k), ...
        tabIled(k));

endfor


fclose(fidTXT);


% ============================================================
% SALVATAGGIO TABELLA HOLD CSV
% ============================================================

holdCSV = ...
    fullfile(outputDir,'tabella_hold.csv');

fidHoldCSV = ...
    fopen(holdCSV,'w');

fprintf(fidHoldCSV, ...
    'V_HOLD_V,tempo_s,N_LED_V,I_LED_mA\n');

for k = 1:length(livelliHold)

    fprintf(fidHoldCSV, ...
        '%.6f,%.9f,%.6f,%.6f\n', ...
        livelliHold(k), ...
        tabTempo(k), ...
        tabVled(k), ...
        tabIled(k));

endfor

fclose(fidHoldCSV);


% ============================================================
% SALVATAGGIO RISULTATI.CSV DELLA SINGOLA PROVA
%
% Una sola riga:
% metadati + risultati.
% ============================================================

resultsCSV = ...
    fullfile(outputDir,'risultati.csv');

fidResCSV = ...
    fopen(resultsCSV,'w');


csvHeader = [ ...
    'timestamp,testID,fileCSV,' ...
    'RGAIN_ohm,RSENS_ohm,' ...
    'frequenza_Hz,numeroImpulsi,durataBurst_ms,' ...
    'VGEN_V,IPD_uA,dutyCycle_pct,' ...
    'VCC_V,VholdBase_V,VholdMax_V,tHoldMax_s,' ...
    'tauHold_s,R2Hold,Capp_uF,' ...
    'IledMax_mA,tIledMax_s,' ...
    'tempoLedAcceso_s,' ...
    'tLedStart_s,tLedPeak_s,tLedEnd_s,' ...
    'transitionTime_ms,' ...
    'VholdLedStart_V,VholdLedPeak_V,VholdLedEnd_V,' ...
    'IledStart_mA,IledPeak_mA,IledEnd_mA,' ...
    'dVledMax_Vs,' ...
    'ledPeakFraction,ledBin_ms,ledSlopeWindow_ms' ...
    ];


fprintf(fidResCSV, ...
    '%s\n', ...
    csvHeader);


fprintf(fidResCSV, ...
    ['"%s","%s","%s",' ...
     '%.6f,%.6f,' ...
     '%.6f,%d,%.6f,' ...
     '%.6f,%.6f,%.6f,' ...
     '%.6f,%.6f,%.6f,%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f\n'], ...
     timestamp, ...
     testID, ...
     filename, ...
     RGAIN_ohm, ...
     RSENS_ohm, ...
     frequenza_Hz, ...
     numeroImpulsi, ...
     durataBurst_ms, ...
     VGEN_V, ...
     IPD_uA, ...
     dutyCycle_pct, ...
     VCC, ...
     VholdBase, ...
     VholdMax, ...
     tHoldMax, ...
     tauHold, ...
     R2hold, ...
     Capp_uF, ...
     IledMax, ...
     tIledMax, ...
     tempoLedAcceso_s, ...
     tLedStart, ...
     tLedPeak, ...
     tLedEnd, ...
     transitionTime_ms, ...
     VholdLedStart, ...
     VholdLedPeak, ...
     VholdLedEnd, ...
     IledStart, ...
     IledPeak, ...
     IledEnd, ...
     dLedMax, ...
     ledPeakFraction, ...
     ledBin_ms, ...
     ledSlopeWindow_ms);

fclose(fidResCSV);


% ============================================================
% AGGIORNAMENTO DATABASE CUMULATIVO
%
% Se il file non esiste viene creata anche l'intestazione.
% Altrimenti viene aggiunta semplicemente una nuova riga.
% ============================================================

cumulativeExists = ...
    (exist(cumulativeCSV,'file') == 2);


fidCum = ...
    fopen(cumulativeCSV,'a');


if (!cumulativeExists)

    fprintf(fidCum, ...
        '%s\n', ...
        csvHeader);

endif


fprintf(fidCum, ...
    ['"%s","%s","%s",' ...
     '%.6f,%.6f,' ...
     '%.6f,%d,%.6f,' ...
     '%.6f,%.6f,%.6f,' ...
     '%.6f,%.6f,%.6f,%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,%.9f,%.9f,' ...
     '%.9f,' ...
     '%.9f,%.9f,%.9f\n'], ...
     timestamp, ...
     testID, ...
     filename, ...
     RGAIN_ohm, ...
     RSENS_ohm, ...
     frequenza_Hz, ...
     numeroImpulsi, ...
     durataBurst_ms, ...
     VGEN_V, ...
     IPD_uA, ...
     dutyCycle_pct, ...
     VCC, ...
     VholdBase, ...
     VholdMax, ...
     tHoldMax, ...
     tauHold, ...
     R2hold, ...
     Capp_uF, ...
     IledMax, ...
     tIledMax, ...
     tempoLedAcceso_s, ...
     tLedStart, ...
     tLedPeak, ...
     tLedEnd, ...
     transitionTime_ms, ...
     VholdLedStart, ...
     VholdLedPeak, ...
     VholdLedEnd, ...
     IledStart, ...
     IledPeak, ...
     IledEnd, ...
     dLedMax, ...
     ledPeakFraction, ...
     ledBin_ms, ...
     ledSlopeWindow_ms);

fclose(fidCum);


% ============================================================
% FIGURA 1
% HOLD + FIT ESPONENZIALE
% ============================================================

figure(1);
clf;

plot(t,vHold,'-');
hold on;

plot(tabTempo,livelliHold,'o');

tHoldPlot = linspace( ...
    tHoldMax, ...
    max(tabTempo), ...
    1500);

vHoldFitPlot = ...
    VholdBase + ...
    AHold.*exp( ...
        -(tHoldPlot-tHoldMax)./tauHold);

plot(tHoldPlot,vHoldFitPlot,'--');

grid on;

xlabel('Tempo [s]');
ylabel('V_{HOLD} [V]');

title(sprintf( ...
    'GX-TXT-v3 - Scarica di HOLD - tau = %.3f s', ...
    tauHold));

legend( ...
    'V_{HOLD} misurata', ...
    'Punti tabella', ...
    'Fit esponenziale', ...
    'location','northeast');

xlim([0 max(tabTempo)]);

print( ...
    fullfile(outputDir,'01_hold_fit.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 2
% N_LED COMPLETO
% ============================================================

figure(2);
clf;

plot(t,vLed,'-');

grid on;

xlabel('Tempo [s]');
ylabel('N\_LED\_ARANCIO [V]');

title( ...
    'GX-TXT-v3 - Tensione sul nodo N\_LED\_ARANCIO');

xlim([t(1) t(end)]);
ylim([0 10]);

print( ...
    fullfile(outputDir,'02_n_led_completo.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 3
% ACCENSIONE RAPIDA LED
% ============================================================

figure(3);
clf;

plot(t,vLed,'-');

grid on;

xlabel('Tempo [s]');
ylabel('N\_LED\_ARANCIO [V]');

title( ...
    'GX-TXT-v3 - Accensione del LED dopo il burst');

xlim([-0.020 0.020]);
ylim([0 10]);

print( ...
    fullfile(outputDir,'03_accensione_led_zoom.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 4
% CORRENTE LED
% ============================================================

figure(4);
clf;

plot(t,iLed_mA,'-');

grid on;

xlabel('Tempo [s]');
ylabel('I_{LED} [mA]');

title( ...
    'GX-TXT-v3 - Corrente del LED arancio nel tempo');

xlim([t(1) t(end)]);

print( ...
    fullfile(outputDir,'04_corrente_led_tempo.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 5
% TRANSIZIONE LED DALLA DERIVATA
% ============================================================

figure(5);
clf;

h1 = plot( ...
    tLedSlope, ...
    dVled_dt, ...
    '-');

hold on;


yTop = ...
    1.12*dLedMax;


xLedMin = max( ...
    tLedSlope(1), ...
    tLedStart-ledPlotMargin);

xLedMax = min( ...
    tLedSlope(end), ...
    tLedEnd+ledPlotMargin);


h2 = plot( ...
    [xLedMin xLedMax], ...
    [thresholdLed thresholdLed], ...
    '--');


h3 = plot( ...
    [tLedStart tLedStart], ...
    [0 yTop], ...
    '--');


h4 = plot( ...
    tLedPeak, ...
    dLedMax, ...
    'o');


h5 = plot( ...
    [tLedEnd tLedEnd], ...
    [0 yTop], ...
    '--');


grid on;

xlabel('Tempo [s]');
ylabel('dV_{NLED}/dt [V/s]');

title(sprintf( ...
    ['GX-TXT-v3 - Transizione LED dalla derivata ' ...
     '- media %.0f ms, finestra %.0f ms'], ...
    ledBin_ms, ...
    ledSlopeWindow_ms));


xlim([xLedMin xLedMax]);
ylim([0 yTop]);


legend( ...
    [h1 h2 h3 h4 h5], ...
    'Derivata N_LED', ...
    'Soglia automatica', ...
    'Inizio transizione', ...
    'Massima pendenza', ...
    'Fine transizione', ...
    'location','northeast');


print( ...
    fullfile( ...
        outputDir, ...
        '05_derivata_led_transizione.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 6
% CARICA RAPIDA HOLD
% ============================================================

figure(6);
clf;

plot(t,vHold,'-');

grid on;

xlabel('Tempo [s]');
ylabel('V_{HOLD} [V]');

title( ...
    'GX-TXT-v3 - Carica rapida del nodo HOLD');

xlim([ ...
    -holdFastPre_ms/1000 ...
    tHoldMax + holdFastPost_ms/1000 ...
]);

print( ...
    fullfile(outputDir,'06_hold_carica_zoom.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 7
% DERIVATA RAPIDA HOLD
% ============================================================

figure(7);
clf;

plot( ...
    tHoldFastSlope, ...
    dVholdFast_dt, ...
    '-');

grid on;

xlabel('Tempo [s]');
ylabel('dV_{HOLD}/dt [V/s]');

title( ...
    'GX-TXT-v3 - Derivata di HOLD durante la carica');

xlim([ ...
    -holdFastPre_ms/1000 ...
    tHoldMax + holdFastPost_ms/1000 ...
]);

print( ...
    fullfile( ...
        outputDir, ...
        '07_hold_derivata_carica.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 8
% DERIVATA HOLD DURANTE LA SCARICA
% ============================================================

idxHDis = find( ...
    tHoldSlowSlope > ...
    tHoldMax+holdDischargeDelay);


tHDis = ...
    tHoldSlowSlope(idxHDis);

dHDis = ...
    dVholdSlow_dt(idxHDis);


dHfit = ...
    -(AHold/tauHold) .* ...
    exp( ...
        -(tHDis-tHoldMax)./tauHold);


figure(8);
clf;

plot(tHDis,dHDis,'-');
hold on;

plot(tHDis,dHfit,'--');

grid on;

xlabel('Tempo [s]');
ylabel('dV_{HOLD}/dt [V/s]');

title( ...
    'GX-TXT-v3 - Velocita di scarica del nodo HOLD');

legend( ...
    'Derivata sperimentale filtrata', ...
    'Derivata del fit esponenziale', ...
    'location','southeast');

xlim([tHDis(1) tHDis(end)]);


print( ...
    fullfile( ...
        outputDir, ...
        '08_hold_derivata_scarica.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FIGURA 9
% I_LED = f(V_HOLD)
% ============================================================

figure(9);
clf;

plot( ...
    vHold(idxHoldMax:end), ...
    iLed_mA(idxHoldMax:end), ...
    '-');

hold on;


plot( ...
    VholdLedStart, ...
    IledStart, ...
    'o');

plot( ...
    VholdLedPeak, ...
    IledPeak, ...
    'o');

plot( ...
    VholdLedEnd, ...
    IledEnd, ...
    'o');


grid on;

xlabel('V_{HOLD} [V]');
ylabel('I_{LED} [mA]');

title( ...
    'GX-TXT-v3 - Corrente LED in funzione di V_{HOLD}');


legend( ...
    'Misura', ...
    'Inizio transizione', ...
    'Massima pendenza', ...
    'Fine transizione', ...
    'location','southeast');


xlim([ ...
    max(0,VholdBase-0.2) ...
    VholdMax+0.2 ...
]);


print( ...
    fullfile( ...
        outputDir, ...
        '09_corrente_led_vs_hold.png'), ...
    '-dpng', ...
    sprintf('-r%d',pngDPI));


% ============================================================
% FINE
% ============================================================

printf('\n');
printf('============================================================\n');
printf('FILE SALVATI\n');
printf('============================================================\n\n');

printf('Cartella prova:\n');
printf('%s\n\n',outputDir);

printf('metadati.txt\n');
printf('risultati.txt\n');
printf('risultati.csv\n');
printf('tabella_hold.csv\n');

printf('\n');

printf('01_hold_fit.png\n');
printf('02_n_led_completo.png\n');
printf('03_accensione_led_zoom.png\n');
printf('04_corrente_led_tempo.png\n');
printf('05_derivata_led_transizione.png\n');
printf('06_hold_carica_zoom.png\n');
printf('07_hold_derivata_carica.png\n');
printf('08_hold_derivata_scarica.png\n');
printf('09_corrente_led_vs_hold.png\n');

printf('\n');

printf('Database cumulativo:\n');
printf('%s\n',cumulativeCSV);

printf('\nAnalisi completata.\n');
