% -----------------------------------------------------------
% This is TikZ Osci package
%
% It allows you to produce oscilloscope "screen shots".
%
% It is based on TikZ and pgfplots and is a replacement can-
% didate to the pstricks pst-osci package which is not main-
% tained anymore.
%
% Author: Thibault Giauffret
% Date: 2023/10/24
% Version: 0.4.0
% Licence : Released under the LaTeX Project Public License v1.3c or later, see http://www.latex-project.org/lppl.txtf
% Not an expert... Just doing it for fun.
% -----------------------------------------------------------

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tikz-osci}[2023/10/24 0.4.0 Tikz Osci package]

% Required packages
\RequirePackage[dvipsnames]{xcolor}
\RequirePackage{pgfkeys}
\RequirePackage{pgfplots}
\RequirePackage{tikz}
\usetikzlibrary{arrows,shapes,positioning,decorations.markings,decorations.pathmorphing,
  decorations.pathreplacing,calc,patterns,shapes.geometric}

% Raised text
\newcommand*{\raisedtext}[1]{%
  \begingroup
    \leavevmode
    \rlap{\kern-.2pt\raise.2pt\hbox{\color{white}#1}}%
    \rlap{\kern.2pt\raise-.2pt\hbox{\color{black!30}#1}}%
    \hbox{#1}%
  \endgroup
}

% The main command
\newcommand\osci[1][]{

  % Init the keys and get the values and add the user's values
  \pgfkeys{
    /osci/.cd,
    scale/.store in=\scale,
    scale=1,
    rounded corners/.store in=\roundedCorners,
    rounded corners=10,
    second channel/.store in=\secondChannel,
    second channel=0,
    screen offset one/.store in=\screenOffsetOne,
    screen offset one=0,
    screen offset two/.store in=\screenOffsetTwo,
    screen offset two=-0,
    time div/.store in=\timeDiv,
    time div=20,
    voltage div one/.store in=\voltageDivOne,
    voltage div one=1,
    voltage div two/.store in=\voltageDivTwo,
    voltage div two=1,
    sample rate/.store in=\sampleRate,
    sample rate=200,
    xy mode/.store in=\xyMode,
    xy mode=0,
    math mode/.store in=\mathMode,
    math mode=0,
    math mode hide source/.store in=\mathModeHideSource,
    math mode hide source=0,
    func one/.store in=\funcOne,
    func one=2*sin(2*180/0.020*x),
    func two/.store in=\funcTwo,
    func two=0.6*sin(2*180/0.020*x)+0.2*sin(2*180/0.040*x),
    indicators/.store in=\indicators,
    indicators=1,
    vertical cursor one/.store in=\verticalCursorOne,
    vertical cursor one=false,
    vertical cursor two/.store in=\verticalCursorTwo,
    vertical cursor two=false,
    horizontal cursor one/.store in=\horizontalCursorOne,
    horizontal cursor one=false,
    horizontal cursor two/.store in=\horizontalCursorTwo,
    horizontal cursor two=false,
    cursor precision/.store in=\cursorPrecision,
    cursor precision=1,
    color one/.store in=\colorOne,
    color one=D62626,
    color text one/.store in=\colorTextOne,
    color text one=FFFFFF,
    color two/.store in=\colorTwo,
    color two=1053AF,
    color text two/.store in=\colorTextTwo,
    color text two=FFFFFF,
    color three/.store in=\colorThree,
    color three=2E8B73,
    color text three/.store in=\colorTextThree,
    color text three=FFFFFF,
    graph back color/.store in=\graphBackColor,
    graph back color=FFFFFF,
    info back color/.store in=\infoBackColor,
    info back color=D6D6D6,
    info text color/.store in=\infoTextColor,
    info text color=000000,
    main axis color/.store in=\mainAxisColor,
    main axis color=000000,
    grid color/.store in=\gridColor,
    grid color=AAAAAA,
    horizontal cursor color/.store in=\horizontalCursorColor,
    horizontal cursor color=FFA500,
    vertical cursor color/.store in=\verticalCursorColor,
    vertical cursor color=800080,
    smooth one/.store in=\smoothOne,
    smooth one=0,
    smooth two/.store in=\smoothTwo,
    smooth two=0,
    smooth three/.store in=\smoothThree,
    smooth three=0,
    #1
  }


  % Set the scale of the picture
  \scalebox{\scale}{
    % Begin the picture
    \begin{tikzpicture}

      % Set the colors
      \definecolor{firstcolor}{HTML}{\colorOne}
      \definecolor{secondcolor}{HTML}{\colorTwo}
      \definecolor{thirdcolor}{HTML}{\colorThree}
      \definecolor{graphbackcolor}{HTML}{\graphBackColor}
      \definecolor{infoBackColor}{HTML}{\infoBackColor}
      \definecolor{infoTextColor}{HTML}{\infoTextColor}
      \definecolor{mainAxisColor}{HTML}{\mainAxisColor}
      \definecolor{gridColor}{HTML}{\gridColor}
      \definecolor{colorTextOne}{HTML}{\colorTextOne}
      \definecolor{colorTextTwo}{HTML}{\colorTextTwo}
      \definecolor{colorTextThree}{HTML}{\colorTextThree}
      \definecolor{verticalCursorColor}{HTML}{\verticalCursorColor}
      \definecolor{horizontalCursorColor}{HTML}{\horizontalCursorColor}

      % Draw the info box
      \draw[black,thick, fill= infoBackColor]
      (0,0) --
      ++(10,0) {[rounded corners=\roundedCorners] --
        ++(0,-1.5) --
        ++(-10,0)} --
      cycle
        {};

      % Add time/div label
      \draw (5,-0.15) node[anchor=north, color= infoTextColor] {\timeDiv\ ms/div};

      % Test if smoothOne is enabled
      \ifnum\smoothOne=1
        % set \smoothOne to smooth
        \def\smoothOne{smooth}
      \else
        % set \smoothOne to empty
        \def\smoothOne{}
      \fi

      % Test if smoothTwo is enabled
      \ifnum\smoothTwo=1
        % set \smoothTwo to smooth
        \def\smoothTwo{smooth}
      \else
        % set \smoothTwo to empty
        \def\smoothTwo{}
      \fi

      % Test if smoothThree is enabled
      \ifnum\smoothThree=1
        % set \smoothThree to smooth
        \def\smoothThree{smooth}
      \else
        % set \smoothThree to empty
        \def\smoothThree{}
      \fi

      % Add XY mode indicator
      % Lissajou mode
      \ifnum\xyMode=1

        \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
        \draw (5,-0.75) node[anchor=north, color=colorTextThree] {XY mode};

      \else

        % Add mode
        \ifnum\mathMode=1

          \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
          \draw (5,-0.75) node[anchor=north, color=colorTextThree] {Add};

        \else

          % Substract mode
          \ifnum\mathMode=2

            \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
            \draw (5,-0.75) node[anchor=north, color=colorTextThree] {Substract};

          \else

            % Multiply mode
            \ifnum\mathMode=3

              \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
              \draw (5,-0.75) node[anchor=north, color=colorTextThree] {Multiply};

            \else

              % Divide mode
              \ifnum\mathMode=4

                \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
                \draw (5,-0.75) node[anchor=north, color=colorTextThree] {Divide};

              \fi
            \fi
          \fi
        \fi
      \fi

      % Add voltage/div label for the first channel
      \draw[firstcolor,fill=firstcolor] (0.5,-0.15) rectangle (1.5,-0.6);
      \draw (1,-0.1) node[anchor=north, color=colorTextOne] {CH1};
      \draw (1,-0.75) node[anchor=north, color= infoTextColor] {\voltageDivOne\ V/div};

      % Add voltage/div label for the second channel
      \ifnum\secondChannel=1
        \draw[secondcolor,fill=secondcolor] (8.5,-0.15) rectangle (9.5,-0.6);
        \draw (9,-0.1) node[anchor=north, color=colorTextTwo]{CH2};
        \draw (9,-0.75) node[anchor=north, color= infoTextColor] {\voltageDivTwo\ V/div};
      \fi

      % Draw the oscilloscope screen border
      \draw[black,thick, fill= graphbackcolor]
      (0,0) --
      ++(10,0) {[rounded corners=\roundedCorners] --
        ++(0,8) --
        ++(-10,0)} --
      cycle
        {};

      % Draw the oscilloscope screen graduations
      \begin{scope}

        % Remove the border
        \clip (0.05,0.05) rectangle (9.95,7.95);

        \begin{axis}[xmin=-5*(\timeDiv/1000), xmax=5*(\timeDiv/1000), ymin=-4, ymax=4, xtick distance = \timeDiv/1000,
            axis x line=middle, axis y line=middle,
            axis line style={-},
            color=mainAxisColor,
            % Draw major grid
            grid=both,
            xticklabels={,,},
            yticklabels={,,},
            % Add sub ticks for the x axis
            minor tick num=4,
            % Remove minor grid
            minor grid style={line width=0pt, draw=white, draw opacity=0},
            major grid style={thick,dashed,draw=gridColor},
            every major tick/.append style={very thick, major tick length=6pt, color=mainAxisColor},
            every minor tick/.append style={thick, minor tick length=4pt, color=mainAxisColor},
          ]

          % Change plot width
          \pgfplotsset{width=11.58cm, height=9.58cm}
          % Change tick label style
          \pgfplotsset{ every non boxed x axis/.append style={x axis line style=-},
            every non boxed y axis/.append style={y axis line style=-}}

          % Lissajous mode
          \ifnum\xyMode=1
            \addplot
            [domain=0:360,variable=\x,
              samples=200,very thick,color=thirdcolor, \smoothThree]
            ({(\funcOne)/\voltageDivOne},{(\funcTwo)/\voltageDivTwo});
            \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
            \draw (5,-0.75) node[anchor=north, color=white] {XY mode};

          \else

            % Show source signals
            \ifnum\mathModeHideSource=0
              % Draw each channel separately
              % First channel plot
              \addplot[color=firstcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000),samples=\sampleRate,\smoothOne]{(\funcOne)/\voltageDivOne+\screenOffsetOne};

              % If the second channel is enabled, draw it
              \ifnum\secondChannel=1
                % Draw the second channel
                \addplot[color=secondcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000), samples=\sampleRate,\smoothTwo]{(\funcTwo)/\voltageDivTwo+\screenOffsetTwo};

              \fi
            \fi

            % Add mode
            \ifnum\mathMode=1
              \addplot[color=thirdcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000),
                smooth, samples=\sampleRate, \smoothThree]{(\funcOne)/\voltageDivOne + (\funcTwo)/\voltageDivTwo};

            \else

              % Substract mode
              \ifnum\mathMode=2
                \addplot[color=thirdcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000), samples=\sampleRate, \smoothThree]{(\funcOne)/\voltageDivOne - (\funcTwo)/\voltageDivTwo};
                \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
                \draw (5,-0.75) node[anchor=north, color=white] {Substract};

              \else

                % Multiply mode
                \ifnum\mathMode=3
                  \addplot[color=thirdcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000) ,samples=\sampleRate, \smoothThree]{(\funcOne)/\voltageDivOne * (\funcTwo)/\voltageDivTwo};
                  \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
                  \draw (5,-0.75) node[anchor=north, color=white] {Multiply};

                \else

                  % Divide mode
                  \ifnum\mathMode=4
                    \addplot[color=thirdcolor,very thick,domain=-5*(\timeDiv/1000):5*(\timeDiv/1000), samples=\sampleRate, \smoothThree]{(\funcOne)/\voltageDivOne / (\funcTwo)/\voltageDivTwo};
                    \draw[thirdcolor,fill=thirdcolor] (4,-0.78) rectangle (6,-1.28);
                    \draw (5,-0.75) node[anchor=north, color=white] {Divide};
                  \fi
                \fi
              \fi
            \fi
          \fi

        \end{axis}

        \ifnum\xyMode=1
        \else
          % Show the channel indicators
          \ifnum\indicators=1
            % Draw the first channel's screen marker
            \draw[firstcolor,fill=firstcolor] (0.4, \screenOffsetOne+4) -- (0, \screenOffsetOne+4+0.3) -- (0, \screenOffsetOne+4-0.3) -- cycle;
            \draw (-0.04, \screenOffsetOne+4) node[anchor=west, color=colorTextOne,font=\fontsize{8}{10}\selectfont] {1};


            % Draw the second channel's screen marker
            \ifnum\secondChannel=1
              \draw[secondcolor,fill=secondcolor] (0.4, \screenOffsetTwo+4) -- (0, \screenOffsetTwo+4+0.3) -- (0, \screenOffsetTwo+4-0.3) -- cycle;
              \draw (-0.04, \screenOffsetTwo+4) node[anchor=west, color=colorTextTwo,font=\fontsize{8}{10}\selectfont] {2};
            \fi
          \fi


          % Draw the vertical cursors

          % Define the false value
          \def\false{false}

          % Set the value of \verticalCursorOne
          \pgfmathsetmacro{\verticalCursorOneValue}{\verticalCursorOne*\timeDiv}
          

          % If the first vertical cursor is enabled
          \ifx\verticalCursorOne\false
          \else
            % Draw the first vertical cursor with \verticalCursorOne value
            \draw[verticalCursorColor,very thick,dashed] (\verticalCursorOne+5,0) -- (\verticalCursorOne+5,8);
            \draw[verticalCursorColor,very thick,fill=verticalCursorColor] (\verticalCursorOne+5-0.25,7.5) rectangle (\verticalCursorOne+5+0.25,8);

            % Draw the indicator
            \draw[white,very thick] (\verticalCursorOne+5,7.45) node[anchor=south, color=white,font=\fontsize{10}{12}\selectfont] {A};

            % Draw the legend
            \draw[verticalCursorColor,very thick] (0.25,0.5) node[anchor=west, color=verticalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurA \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\verticalCursorOneValue}\ ms}};

            % If the second vertical cursor is enabled
            \ifx\verticalCursorTwo\false
            \else
              % Draw the time difference between the two vertical cursors
              \pgfmathsetmacro{\verticalCursorDiff}{\verticalCursorTwo-\verticalCursorOne}
              \pgfmathsetmacro{\verticalCursorDiffValue}{\verticalCursorDiff*\timeDiv}
              \draw[verticalCursorColor,very thick] (0.25,1.5) node[anchor=west, color=verticalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurB - CurA \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\verticalCursorDiffValue}\ ms}};
            \fi

          \fi

          % Set the value of \verticalCursorTwo
          \pgfmathsetmacro{\verticalCursorTwoValue}{\verticalCursorTwo*\timeDiv}

          % If the second vertical cursor is enabled
          \ifx\verticalCursorTwo\false
          \else
            % Draw the second vertical cursor with \verticalCursorTwo value
            \draw[verticalCursorColor,very thick,dashed] (\verticalCursorTwo+5,0) -- (\verticalCursorTwo+5,8);
            \draw[verticalCursorColor,very thick,fill=verticalCursorColor] (\verticalCursorTwo+5-0.25,7.5) rectangle (\verticalCursorTwo+5+0.25,8);

            % Draw the indicator
            \draw[white,very thick] (\verticalCursorTwo+5,7.45) node[anchor=south, color=white,font=\fontsize{10}{12}\selectfont] {B};

            % Draw the legend
            \draw[verticalCursorColor,very thick] (0.25,1) node[anchor=west, color=verticalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurB \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\verticalCursorTwoValue}\ ms}};

          \fi


          % Draw the horizontal cursors

          % Set the value of \horizontalCursorOne
          \pgfmathsetmacro{\horizontalCursorOneValue}{\horizontalCursorOne*\voltageDivOne}

          % If the first horizontal cursor is enabled
          \ifx\horizontalCursorOne\false
          \else
            % Draw the first horizontal cursor with \horizontalCursorOne value
            \draw[horizontalCursorColor,very thick,dashed] (0,\horizontalCursorOne+4) -- (10,\horizontalCursorOne+4);
            \draw[horizontalCursorColor,very thick,fill=horizontalCursorColor] (9.5,\horizontalCursorOne+4-0.25) rectangle (10.5,\horizontalCursorOne+4+0.25);
            
            % Draw the indicator
            \draw[white,very thick] (10,\horizontalCursorOne+4) node[anchor=east, color=white,font=\fontsize{10}{12}\selectfont] {A};

            % Draw the legend
            \draw[horizontalCursorColor,very thick] (5.25,0.5) node[anchor=west, color=horizontalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurA \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\horizontalCursorOneValue}\ V}};

            % If the second horizontal cursor is enabled
            \ifx\horizontalCursorTwo\false
            \else
              % Draw the voltage difference between the two horizontal cursors
              \pgfmathsetmacro{\horizontalCursorDiff}{\horizontalCursorTwo-\horizontalCursorOne}
              \pgfmathsetmacro{\horizontalCursorDiffValue}{\horizontalCursorDiff*\voltageDivOne}
              \draw[horizontalCursorColor,very thick] (5.25,1.5) node[anchor=west, color=horizontalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurB - CurA \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\horizontalCursorDiffValue}\ V}};
            \fi
          \fi

          % Set the value of \horizontalCursorTwo
          \pgfmathsetmacro{\horizontalCursorTwoValue}{\horizontalCursorTwo*\voltageDivOne}

          % If the second horizontal cursor is enabled
          \ifx\horizontalCursorTwo\false
          \else
            % Draw the second horizontal cursor with \horizontalCursorTwo value
            \draw[horizontalCursorColor,very thick,dashed] (0,\horizontalCursorTwo+4) -- (10,\horizontalCursorTwo+4);
            \draw[horizontalCursorColor,very thick,fill=horizontalCursorColor] (9.5,\horizontalCursorTwo+4-0.25) rectangle (10.5,\horizontalCursorTwo+4+0.25);

            % Draw the indicator
            \draw[white,very thick] (10,\horizontalCursorTwo+4) node[anchor=east, color=white,font=\fontsize{10}{12}\selectfont] {B};

            % Draw the legend
            \draw[horizontalCursorColor,very thick] (5.25,1) node[anchor=west, color=horizontalCursorColor,font=\fontsize{10}{12}\selectfont] {\raisedtext{CurB \pgfmathprintnumber[precision=\cursorPrecision, assume math mode=true,fixed zerofill]{\horizontalCursorTwoValue}\ V}};

          \fi

          % End xyMode test
        \fi

      \end{scope}

    \end{tikzpicture}
  }
}