% hlavní skript

clear;

db = readtable('mice_db.xlsx'); % tabulka z databáze
Fs = db{1, "Fs"}; % vzorkovací frekvence
period = db{1, "period"}; % délka měření jednotlivých souborů

switch Fs % nastavení vzorkovací frekvence pro IntanBoard
    case 1000
        SamplingRate = rhd2000.SamplingRate.rate1000;
    case 1250
        SamplingRate = rhd2000.SamplingRate.rate1250;
    case 1500
        SamplingRate = rhd2000.SamplingRate.rate1500;
    case 2000
        SamplingRate = rhd2000.SamplingRate.rate2000;
    case 2500
        SamplingRate = rhd2000.SamplingRate.rate2500;
    case 3000
        SamplingRate = rhd2000.SamplingRate.rate3000;
    case 3333
        SamplingRate = rhd2000.SamplingRate.rate3333;
    case 4000
        SamplingRate = rhd2000.SamplingRate.rate4000;
    case 5000
        SamplingRate = rhd2000.SamplingRate.rate5000;
    case 6250
        SamplingRate = rhd2000.SamplingRate.rate6250;
    case 8000
        SamplingRate = rhd2000.SamplingRate.rate8000;
    case 10000
        SamplingRate = rhd2000.SamplingRate.rate10000;
    case 12500
        SamplingRate = rhd2000.SamplingRate.rate12500;
    case 15000
        SamplingRate = rhd2000.SamplingRate.rate15000;
    case 20000
        SamplingRate = rhd2000.SamplingRate.rate20000;
    case 25000
        SamplingRate = rhd2000.SamplingRate.rate25000;
    case 30000
        SamplingRate = rhd2000.SamplingRate.rate30000;
    otherwise
        error('vzorkovací frekvence je nedostupná pro Intanboard')
end
%% driver a handle pro IntanBoard
driver = rhd2000.Driver;
board = driver.create_board();
params = board.get_configuration_parameters();

%% nastavení IntanBoardu
params.Board.DigitalOutputs.ComparatorsEnabled = false;
params.Chip.Bandwidth.DesiredLower = 1;
params.Chip.Bandwidth.DesiredUpper = Fs/2 - 100;
params.Driver.NumBlocksToRead = 60;
board.set_configuration_parameters(params);
board.SamplingRate = SamplingRate;

board.flush(); % vyčištění fronty

datablock = rhd2000.datablock.DataBlock(board); % alokování paměti pro datablok
board.run_continuously(); % spuštění desky
change = 0; % logická proměnná pro založení nového souboru s daty
on = 0; % logická proměnná pro čtení kódu z Funduina
p = 1; % čítač znaků kódu
IDtag = 0; % nejpozději přijatý kód
recording = 0; % logická proměnná pro nahrávání
Subject = "test";
ChName = "1, 2";
SigEnd = 0;
start_table = 0; % logická proměnná pro založení nové složky
bitnumber = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
end_table = 0; % logická proměnná pro ukončení složky
counter = 0; % čítač nahrávaných SPI
place = 1; % čítač pro seznam nahrávaných SPI
dim = []; % dimenze pro tabulku pro ukládaní do správného formátu
mice = []; % tabulka nahráváných SPI
IDtag_history = [0]; % historie přijatých kódů
Data1 = [];
Data2 = []; % inicializace pro data z SPI
saving = 2; % čítač pro ukládání po daném intervalu
first_change = period; % čítač pro založení nového souboru
change_file1 = 0; % čítač pro číslování souborů
second_change = period;
change_file2 = 0;
flush_control = 0; % logická proměnná na zapnutí desky po restartu



disp("ready");
while true
    datablock = board.read_next_data_block();
    for j = 1:60
        if datablock.Board.DigitalInputs(2,j) == 1 && on == 0
            on = 1;
            change = 1;
        end
        if datablock.Board.DigitalInputs(2,j) == 0 && on == 1
            change = 1;
            on = 0;
        end
        if change == 1
            bitnumber(p) = datablock.Board.DigitalInputs(1,j);
            change = 0;
            p = p + 1;
        end
        if p == 17
            IDtag = bit2dec(bitnumber)
            bitnumber = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
            p = 1;
            on = 0;
            for i = 1:height(db)
                if IDtag == db{i, 1} % if IDtag is not in db, nothing happens, no new table is set up
                    for l = 1:length(IDtag_history)
                        if IDtag_history(l) == IDtag
                            end_table = 1;
                            break;
                        end
                    end
                    if end_table ~= 1
                        start_table = 1;
                        IDtag_history(end+1) = IDtag;
                    end
                    recording = IDtag; % logická proměnná má v sobě poslední IDtag co byl přijat - není 0
                    break;
                end
            end
        end
    end
    if start_table == 1
        [Subject, elektrody, SigStart, SigEnd, Fs, SPI, ChName] = read_db(IDtag, db);
        Data = datablock.Chips{SPI, 1}.Amplifiers(elektrody, :);
        mice{place} = table(Subject, ChName, SigStart, SigEnd, Fs, Data);
        sigTbl = mice{place};
        SPI_history(place) = SPI;
        mkdir([pwd '\' char(Subject(1))]);
        save([pwd '\' char(Subject(1)) '\'  char(Subject(1)) '_-1.mat'],'sigTbl')
        start_table = 0;
        counter = counter + 1
        first = 1; % logická proměnná pro první datablok od přijetí IDtag
        place = place + 1;
    elseif recording ~= 0
        if counter == 1
            if first == 1
                Data1 = mice{place-1}.Data;
                end_saving1 = datetime();
                first = 0;
            end
            SPI1 = SPI_history(place-1);
            elektrody1 = str2double((mice{place-1}.ChName));
            Data1 = [Data1 datablock.Chips{SPI1, 1}.Amplifiers(elektrody1, :)];
        elseif counter == 2
            if first == 1
                Data2 = mice{place - 1}.Data;
                first = 0;   
                end_saving2 = datetime();
            end
            SPI2 = SPI_history(place - 1);
            elektrody2 = str2double((mice{place-1}.ChName));
            Data1 = [Data1 datablock.Chips{SPI1, 1}.Amplifiers(elektrody1, :)];
            Data2 = [Data2 datablock.Chips{SPI2, 1}.Amplifiers(elektrody2, :)];
        end

        if (saving == Fs) | (board.FIFOPercentageFull > 90)
            if counter == 1
                if first_change == period
                    saving_data_change(IDtag_history(2), db, Data1, change_file1, end_saving1, Fs)
                    change_file1 = change_file1 + 1;
                    first_change = 1;
                    Data1 = [];
                else
                    [~, end_saving1] = saving_data(IDtag_history(2), db, Data1, change_file1, Fs);
                    Data1 = [];
                    first_change = first_change + 1;
                end
            elseif counter == 2
                if first_change == period
                    saving_data_change(IDtag_history(2), db, Data1, change_file1, end_saving1, Fs)
                    change_file1 = change_file1 + 1;
                    first_change = 1; 
                    Data1 = [];
                else
                    [~, end_saving1] = saving_data(IDtag_history(2), db, Data1, change_file1, Fs);
                    Data1 = [];
                    first_change = first_change + 1;
                end
                if second_change == period
                    saving_data_change(IDtag_history(3), db, Data2, change_file2, end_saving2, Fs)
                    change_file2 = change_file2 + 1;
                    second_change = 1;
                    Data2 = [];
                else
                    [~, end_saving2] = saving_data(IDtag_history(3), db, Data2, change_file2, Fs);
                    Data2 = [];
                    second_change = second_change + 1;
                end
            end
            if board.FIFOPercentageFull > 90
                board.stop();
                flush_control = 1;
            end
            saving = 1;
        else
            saving = saving + 1;
        end
        
    end
    if end_table == 1 % když se ukončí nahrávání jednoho SPI, vezmou se data z daného SPI a uloží se naposledy
        [Subject, elektrody, SigStart, ~, Fs, SPI, ChName] = read_db(IDtag, db);
        for w = 1:length(mice)
            if mice{w}.Subject{1} == Subject(1)
                if w == 1
                    Data = single(Data1);
                    Data1 = Data2;
                    change_file = change_file1; 
                    change_file1 = change_file2; % z dvou nahrávaných SPI se přejde na jedno SPI
                elseif w == 2
                    Data = single(Data2);
                    change_file = change_file2;
                end
                break
            end
        end
        [sigTbl, ~] = saving_data(IDtag, db, Data, change_file, Fs);
        end_table = 0;
        counter = counter - 1
        mice(w) = [];
        SPI_history(w) = [];
        place = place - 1;
        dim = [];
        IDtag_history(w+1) = [];
        if counter == 0
            recording = 0;
            saving = 0;
        end
    end
    if board.FIFOPercentageFull < 1 && flush_control == 1
        board.run_continuously()
        flush_control = 0;
    end
    % percentage = board.FIFOPercentageFull; % procentové zatížení IntanBoardu
end

board.stop()