classdef uPDemoGUI < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                  matlab.ui.Figure
        LinkslaufButton           matlab.ui.control.Button
        RechtslaufButton          matlab.ui.control.Button
        DrehwinkelEditField       matlab.ui.control.NumericEditField
        DrehwinkelEditFieldLabel  matlab.ui.control.Label
        Soll                      matlab.ui.control.Slider
        SollspannungLabel         matlab.ui.control.Label
        Licht                     matlab.ui.control.Slider
        LichtLabel                matlab.ui.control.Label
        Servo                     matlab.ui.control.Knob
        ServoKnobLabel            matlab.ui.control.Label
        status                    matlab.ui.control.Label
        main                      matlab.ui.control.Lamp
        verbindenButton           matlab.ui.control.Button
        zeile10                   matlab.ui.control.Label
        zeile9                    matlab.ui.control.Label
        zeile8                    matlab.ui.control.Label
        zeile7                    matlab.ui.control.Label
        zeile6                    matlab.ui.control.Label
        zeile5                    matlab.ui.control.Label
        zeile4                    matlab.ui.control.Label
        zeile3                    matlab.ui.control.Label
        zeile2                    matlab.ui.control.Label
        zeile1                    matlab.ui.control.Label
        microPythonMCUDemoGUIuPDemoGUILabel  matlab.ui.control.Label
        Y3Switch                  matlab.ui.control.Switch
        Y2Switch                  matlab.ui.control.Switch
        Y1Switch                  matlab.ui.control.Switch
        Y0Switch                  matlab.ui.control.Switch
        Y3Lamp                    matlab.ui.control.Lamp
        Y3LampLabel               matlab.ui.control.Label
        Y2Lamp                    matlab.ui.control.Lamp
        Y2LampLabel               matlab.ui.control.Label
        Y1Lamp                    matlab.ui.control.Lamp
        Y1LampLabel               matlab.ui.control.Label
        Y0Lamp                    matlab.ui.control.Lamp
        Y0LampLabel               matlab.ui.control.Label
        Diagramm                  matlab.ui.control.UIAxes
    end

    
    properties (Access = private)
        device          % microPython Device
        tADC            % Timer für die Spannungsmessung
        buffer          % Datenpuffer
        
        %
        % Flags
        %
        
        flag_start = 0;         % Indikator für den Start
        
    end
    
    
    methods (Access = public)
        
        function PicoSerialRead(app, ~, ~)
            zeile = readline(app.device);
            zeileChars = char(zeile);
            mode = 99;
            
            if zeileChars(1:3) == '>>>'
                zeileChars = zeileChars(5:end);
            end
            
            if zeileChars(1:4) == 'AIN:'
                mode = 1;
            end
            
            if zeileChars(1:4) == 'True'
                mode = 0;
            end
            
            if zeileChars(1:4) == 'pico'
                mode = 0;
            end
            
            if zeileChars(1:5) == 'print'
                mode = 0;
            end

            if zeileChars(1:6) == 'import'
                mode = 0;
            end

            if zeileChars(1:4) == 'pins'
                mode = 0;
            end

            if zeileChars(1:3) == 'out'
                mode = 0;
            end

            if zeileChars(1:3) == 'seq'
                mode = 0;
            end

            
            switch mode
                
                case 1
                    werte = split(zeile);
                    wert = str2num(werte(end));
                
                    if app.flag_start == 0
                        app.buffer = wert;
                        app.flag_start = 1;
                    else
                        app.buffer(end+1) = wert;
                    end
                
                    if length(app.buffer) > 300
                        app.buffer = app.buffer(end-300:end);
                    end
                
                    plot(app.Diagramm, app.buffer);
                    axis(app.Diagramm, [0 inf 0 3.5]);
                    title(app.Diagramm, 'Spannungsmessung');
                    ylabel(app.Diagramm, 'Volt');
                    xlabel(app.Diagramm, 'Messwerte');
            
                case 99
                    app.zeile10.Text =  app.zeile9.Text;
                    app.zeile9.Text =  app.zeile8.Text;
                    app.zeile8.Text =  app.zeile7.Text;
                    app.zeile7.Text =  app.zeile6.Text;
                    app.zeile6.Text =  app.zeile5.Text;
                    app.zeile5.Text =  app.zeile4.Text;
                    app.zeile4.Text =  app.zeile3.Text;
                    app.zeile3.Text =  app.zeile2.Text;
                    app.zeile2.Text =  app.zeile1.Text;
                    app.zeile1.Text =  zeileChars;
            end
            
        end
    end
    

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            app.zeile1.Text = '';
            app.zeile2.Text = '';
            app.zeile3.Text = '';
            app.zeile4.Text = '';
            app.zeile5.Text = '';
            app.zeile6.Text = '';
            app.zeile7.Text = '';
            app.zeile8.Text = '';
            app.zeile9.Text = '';
            app.zeile10.Text = '';
            
            app.main.Color = [1.00,0.00,0.00];
            app.Y0Lamp.Color = [1.00,1.00,1.00];
            app.Y1Lamp.Color = [1.00,1.00,1.00];
            app.Y2Lamp.Color = [1.00,1.00,1.00];
            app.Y3Lamp.Color = [1.00,1.00,1.00];
            
            app.status.Text = 'GUI bereit';
        end

        % Button pushed function: verbindenButton
        function verbindenButtonPushed(app, event)
            app.device = serialport('COM11', 115200);                % Raspberry Pi Pico
            configureTerminator(app.device, 'CR/LF');
            configureCallback(app.device, 'terminator', @app.PicoSerialRead);
            
            writeline(app.device, 'import pico');
            %writeline(app.device, 'pico.dac.write(0)');
            writeline(app.device, 'pico.licht.duty_u16(65536)');
            writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 3)');
            writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 2)');
            writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 1)');
            writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 0)');
            
            for xi=180:-10:0
                value = ceil(8200 - 6000/180*xi);
                writeline(app.device, ['pico.servo.duty_u16(' num2str(value) ')']);
                pause(0.25);
            end
            
            writeline(app.device, 'pico.tasten[0].value(1)');
            writeline(app.device, 'pico.tasten[1].irq(trigger=machine.Pin.IRQ_RISING, handler=pico.isr1_callback)');
            writeline(app.device, 'pico.tasten[2].irq(trigger=machine.Pin.IRQ_RISING, handler=pico.isr2_callback)');
            
            writeline(app.device, ['pico.licht.duty_u16(0)']);
            
            %
            % Schrittmotor initialisieren
            %
            
            writeline(app.device, 'pins = [20, 18, 19, 21]');
            writeline(app.device, 'out = pico.demo.setup(pins)');
            writeline(app.device, 'seq = pico.demo.sequenz()');
            writeline(app.device, 'seq_pos = -1');
            %
            % Spannungsmessung aktivieren
            %
            app.tADC = timer;
            app.tADC.TimerFcn = @(~,~) writeline(app.device,'print("AIN: ", str(pico.ain.read_u16()*3.3/65535))');
            app.tADC.Period = 0.1;
            app.tADC.ExecutionMode = 'fixedRate';
            start(app.tADC);
            
            app.main.Color = [0.00,1.00,0.00];
            
            app.verbindenButton.Enable = 0;
            app.status.Text = 'GUI mit Raspberry Pi Pico verbunden';
        end

        % Value changed function: Y0Switch
        function Y0SwitchValueChanged(app, event)
            value = app.Y0Switch.Value;
            
            if value == 0
                writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 0)');
                app.Y0Lamp.Color = [1.00,1.00,1.00];
            else
                writeline(app.device, 'pico.demo.ventil_on(pico.ventile, 0)');
                app.Y0Lamp.Color = [1.00,1.00,0.00];
            end
        end

        % Value changed function: Y1Switch
        function Y1SwitchValueChanged(app, event)
            value = app.Y1Switch.Value;
            
            if value == 0
                writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 1)');
                app.Y1Lamp.Color = [1.00,1.00,1.00];
            else
                writeline(app.device, 'pico.demo.ventil_on(pico.ventile, 1)');
                app.Y1Lamp.Color = [1.00,1.00,0.00];
            end
        end

        % Value changed function: Y2Switch
        function Y2SwitchValueChanged(app, event)
            value = app.Y2Switch.Value;
            
            if value == 0
                writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 2)');
                app.Y2Lamp.Color = [1.00,1.00,1.00];
            else
                writeline(app.device, 'pico.demo.ventil_on(pico.ventile, 2)');
                app.Y2Lamp.Color = [1.00,1.00,0.00];
            end
        end

        % Value changed function: Y3Switch
        function Y3SwitchValueChanged(app, event)
            value = app.Y3Switch.Value;
            
            if value == 0
                writeline(app.device, 'pico.demo.ventil_off(pico.ventile, 3)');
                app.Y3Lamp.Color = [1.00,1.00,1.00];
            else
                writeline(app.device, 'pico.demo.ventil_on(pico.ventile, 3)');
                app.Y3Lamp.Color = [1.00,1.00,0.00];
            end
        end

        % Value changed function: Servo
        function ServoValueChanged(app, event)
            %
            % Ansteuerung von Servos
            % Takfrequenz 50 Hz ergibt eine Periodendauer von 20 ms
            % Einstellwert 8200 entspricht bei diesem Servo 0 °
            % Einsetllwert 2200 180 °
            %
            % Berechnung:
            % Einstellwert = 8200 - 6000/180*Winkel
            %
            
            value = ceil(8200 - 6000/180*app.Servo.Value);
            
            writeline(app.device, ['pico.servo.duty_u16(' num2str(value) ')']);
        end

        % Value changed function: Licht
        function LichtValueChanged(app, event)
            value = ceil(app.Licht.Value*655.36);
            
            writeline(app.device, ['pico.licht.duty_u16(' num2str(value) ')']);
        end

        % Close request function: UIFigure
        function UIFigureCloseRequest(app, event)
            delete(app.tADC);
            delete(app);
        end

        % Value changed function: Soll
        function SollValueChanged(app, event)
            value = round(app.Soll.Value*4095/3.3);
            writeline(app.device, ['pico.dac.write(' num2str(value) ')']);
        end

        % Button pushed function: LinkslaufButton
        function LinkslaufButtonPushed(app, event)
            value = round(app.DrehwinkelEditField.Value/360*400);
            writeline(app.device, ['seq_pos = pico.demo.backwardStep(' num2str(value) ', seq_pos, seq, out)']);
            writeline(app.device, 'pico.demo.setStepperOff(out)');
            
            app.status.Text = [num2str(app.DrehwinkelEditField.Value) ' ° bzw. ' num2str(value) ' Schritte Schrittmotor Linkslauf'];
        end

        % Button pushed function: RechtslaufButton
        function RechtslaufButtonPushed(app, event)
            value = round(app.DrehwinkelEditField.Value/360*400);
            writeline(app.device, ['seq_pos = schrittmotor.forwardStep(' num2str(value) ', seq_pos, seq, out)']);
            writeline(app.device, 'pico.demo.setStepperOff(out)');
            
                        app.status.Text = [num2str(app.DrehwinkelEditField.Value) ' ° bzw. ' num2str(value) ' Schritte Schrittmotor Rechtslauf'];
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 1068 618];
            app.UIFigure.Name = 'MATLAB App';
            app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);

            % Create Diagramm
            app.Diagramm = uiaxes(app.UIFigure);
            title(app.Diagramm, 'Title')
            xlabel(app.Diagramm, 'X')
            ylabel(app.Diagramm, 'Y')
            zlabel(app.Diagramm, 'Z')
            app.Diagramm.Position = [579 31 448 185];

            % Create Y0LampLabel
            app.Y0LampLabel = uilabel(app.UIFigure);
            app.Y0LampLabel.HorizontalAlignment = 'right';
            app.Y0LampLabel.Position = [30 540 25 22];
            app.Y0LampLabel.Text = 'Y0';

            % Create Y0Lamp
            app.Y0Lamp = uilamp(app.UIFigure);
            app.Y0Lamp.Position = [70 540 20 20];

            % Create Y1LampLabel
            app.Y1LampLabel = uilabel(app.UIFigure);
            app.Y1LampLabel.HorizontalAlignment = 'right';
            app.Y1LampLabel.Position = [30 515 25 22];
            app.Y1LampLabel.Text = 'Y1';

            % Create Y1Lamp
            app.Y1Lamp = uilamp(app.UIFigure);
            app.Y1Lamp.Position = [70 515 20 20];

            % Create Y2LampLabel
            app.Y2LampLabel = uilabel(app.UIFigure);
            app.Y2LampLabel.HorizontalAlignment = 'right';
            app.Y2LampLabel.Position = [30 490 25 22];
            app.Y2LampLabel.Text = 'Y2';

            % Create Y2Lamp
            app.Y2Lamp = uilamp(app.UIFigure);
            app.Y2Lamp.Position = [70 490 20 20];

            % Create Y3LampLabel
            app.Y3LampLabel = uilabel(app.UIFigure);
            app.Y3LampLabel.HorizontalAlignment = 'right';
            app.Y3LampLabel.Position = [30 465 25 22];
            app.Y3LampLabel.Text = 'Y3';

            % Create Y3Lamp
            app.Y3Lamp = uilamp(app.UIFigure);
            app.Y3Lamp.Position = [70 465 20 20];

            % Create Y0Switch
            app.Y0Switch = uiswitch(app.UIFigure, 'slider');
            app.Y0Switch.ItemsData = [0 1];
            app.Y0Switch.ValueChangedFcn = createCallbackFcn(app, @Y0SwitchValueChanged, true);
            app.Y0Switch.Position = [140 540 45 20];
            app.Y0Switch.Value = 0;

            % Create Y1Switch
            app.Y1Switch = uiswitch(app.UIFigure, 'slider');
            app.Y1Switch.ItemsData = [0 1];
            app.Y1Switch.ValueChangedFcn = createCallbackFcn(app, @Y1SwitchValueChanged, true);
            app.Y1Switch.Position = [140 515 45 20];
            app.Y1Switch.Value = 0;

            % Create Y2Switch
            app.Y2Switch = uiswitch(app.UIFigure, 'slider');
            app.Y2Switch.ItemsData = [0 1];
            app.Y2Switch.ValueChangedFcn = createCallbackFcn(app, @Y2SwitchValueChanged, true);
            app.Y2Switch.Position = [140 490 45 20];
            app.Y2Switch.Value = 0;

            % Create Y3Switch
            app.Y3Switch = uiswitch(app.UIFigure, 'slider');
            app.Y3Switch.ItemsData = [0 1];
            app.Y3Switch.ValueChangedFcn = createCallbackFcn(app, @Y3SwitchValueChanged, true);
            app.Y3Switch.Position = [140 465 45 20];
            app.Y3Switch.Value = 0;

            % Create microPythonMCUDemoGUIuPDemoGUILabel
            app.microPythonMCUDemoGUIuPDemoGUILabel = uilabel(app.UIFigure);
            app.microPythonMCUDemoGUIuPDemoGUILabel.HorizontalAlignment = 'center';
            app.microPythonMCUDemoGUIuPDemoGUILabel.FontSize = 24;
            app.microPythonMCUDemoGUIuPDemoGUILabel.Position = [232 573 504 30];
            app.microPythonMCUDemoGUIuPDemoGUILabel.Text = 'microPython MCU Demo - GUI (uPDemoGUI)';

            % Create zeile1
            app.zeile1 = uilabel(app.UIFigure);
            app.zeile1.Position = [30 10 550 22];
            app.zeile1.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile2
            app.zeile2 = uilabel(app.UIFigure);
            app.zeile2.Position = [30 26 550 22];
            app.zeile2.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile3
            app.zeile3 = uilabel(app.UIFigure);
            app.zeile3.Position = [30 42 550 22];
            app.zeile3.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile4
            app.zeile4 = uilabel(app.UIFigure);
            app.zeile4.Position = [30 58 550 22];
            app.zeile4.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile5
            app.zeile5 = uilabel(app.UIFigure);
            app.zeile5.Position = [30 74 550 22];
            app.zeile5.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile6
            app.zeile6 = uilabel(app.UIFigure);
            app.zeile6.Position = [30 90 550 22];
            app.zeile6.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile7
            app.zeile7 = uilabel(app.UIFigure);
            app.zeile7.Position = [30 106 550 22];
            app.zeile7.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile8
            app.zeile8 = uilabel(app.UIFigure);
            app.zeile8.Position = [30 122 550 22];
            app.zeile8.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile9
            app.zeile9 = uilabel(app.UIFigure);
            app.zeile9.Position = [30 138 550 22];
            app.zeile9.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create zeile10
            app.zeile10 = uilabel(app.UIFigure);
            app.zeile10.Position = [30 154 550 22];
            app.zeile10.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create verbindenButton
            app.verbindenButton = uibutton(app.UIFigure, 'push');
            app.verbindenButton.ButtonPushedFcn = createCallbackFcn(app, @verbindenButtonPushed, true);
            app.verbindenButton.FontSize = 18;
            app.verbindenButton.Position = [938 569 100 30];
            app.verbindenButton.Text = 'verbinden';

            % Create main
            app.main = uilamp(app.UIFigure);
            app.main.Position = [892 573 20 20];
            app.main.Color = [0 0 1];

            % Create status
            app.status = uilabel(app.UIFigure);
            app.status.Position = [30 170 550 22];
            app.status.Text = '01234567890123456789012345678901234567890123456789012345678901234567890123456789';

            % Create ServoKnobLabel
            app.ServoKnobLabel = uilabel(app.UIFigure);
            app.ServoKnobLabel.HorizontalAlignment = 'center';
            app.ServoKnobLabel.FontSize = 16;
            app.ServoKnobLabel.Position = [333 307 47 22];
            app.ServoKnobLabel.Text = 'Servo';

            % Create Servo
            app.Servo = uiknob(app.UIFigure, 'continuous');
            app.Servo.Limits = [0 180];
            app.Servo.ValueChangedFcn = createCallbackFcn(app, @ServoValueChanged, true);
            app.Servo.Position = [286 363 142 142];

            % Create LichtLabel
            app.LichtLabel = uilabel(app.UIFigure);
            app.LichtLabel.HorizontalAlignment = 'right';
            app.LichtLabel.FontSize = 16;
            app.LichtLabel.Position = [799 461 39 22];
            app.LichtLabel.Text = 'Licht';

            % Create Licht
            app.Licht = uislider(app.UIFigure);
            app.Licht.ValueChangedFcn = createCallbackFcn(app, @LichtValueChanged, true);
            app.Licht.Position = [613 524 414 3];

            % Create SollspannungLabel
            app.SollspannungLabel = uilabel(app.UIFigure);
            app.SollspannungLabel.HorizontalAlignment = 'right';
            app.SollspannungLabel.FontSize = 16;
            app.SollspannungLabel.Position = [781 386 102 22];
            app.SollspannungLabel.Text = 'Sollspannung';

            % Create Soll
            app.Soll = uislider(app.UIFigure);
            app.Soll.Limits = [0 3.3];
            app.Soll.ValueChangedFcn = createCallbackFcn(app, @SollValueChanged, true);
            app.Soll.Position = [618 449 414 3];

            % Create DrehwinkelEditFieldLabel
            app.DrehwinkelEditFieldLabel = uilabel(app.UIFigure);
            app.DrehwinkelEditFieldLabel.HorizontalAlignment = 'right';
            app.DrehwinkelEditFieldLabel.Position = [620 342 65 22];
            app.DrehwinkelEditFieldLabel.Text = 'Drehwinkel';

            % Create DrehwinkelEditField
            app.DrehwinkelEditField = uieditfield(app.UIFigure, 'numeric');
            app.DrehwinkelEditField.Position = [700 342 100 22];

            % Create RechtslaufButton
            app.RechtslaufButton = uibutton(app.UIFigure, 'push');
            app.RechtslaufButton.ButtonPushedFcn = createCallbackFcn(app, @RechtslaufButtonPushed, true);
            app.RechtslaufButton.Position = [812 342 100 22];
            app.RechtslaufButton.Text = 'Rechtslauf';

            % Create LinkslaufButton
            app.LinkslaufButton = uibutton(app.UIFigure, 'push');
            app.LinkslaufButton.ButtonPushedFcn = createCallbackFcn(app, @LinkslaufButtonPushed, true);
            app.LinkslaufButton.Position = [927 342 100 22];
            app.LinkslaufButton.Text = 'Linkslauf';

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = uPDemoGUI

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end