% ----------------------------------------------------------- % 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} } }