[Tex/LaTex] circuit schematic symbol for buffer with control input

circuitikztikz-pgf

circuitikz has an op amp component type with two inputs, output, and up and down ports, usually used for power supply rails. There's also a buffer component type (which I think is provided by tikz itself, not the circuitikz library) which has one input and one output and no vertical ports.

I'm looking for a buffer/amp with one input, one output, and the vertical ports, for use as control pins. My use case is a track-and-hold (aka sample-and-hold) amplifier symbol, but a tri-state buffers are also very common and require a control input.

circuit exemplifying SHA

Ok, that figure uses a two-input SHA. But I'm sure you can imagine what the one-input version should look like (basically, I'm trying to make a single symbol that hides all that complexity, for a high-level block diagram).

tristate buffer symbols

Does tikz or one of its extension libraries provide such a beast? If not, how can I properly align a vertical wire with the edge of the buffer?

Best Answer

Declaring new node shapes is a bit of a pain, but you get used to it. Here are two new circuit shapes tri state buffer active low and tri state buffer active high that behave like buffer gate and not gate, but offer a new anchor control. This allows you to draw this:

using this:

\begin{tikzpicture}[circuit logic US, on grid]
\node (i) {x};
\node (buf) [right of=i, tri state buffer active high] {};
\node (ctrl) [above=of buf] {c};
\node (o) [right of=buf] {y};

\draw (i) -- (buf.input)
    (ctrl) -- (buf.control)
    (buf.output) -- (o);
\end{tikzpicture}%

\begin{tikzpicture}[circuit logic US, on grid]
\node (i) {x};
\node (buf) [right of=i, tri state buffer active low] {};
\node (ctrl) [above=1 of buf] {c};
\node (o) [right of=buf] {y};

\draw (i) -- (buf.input)
    (ctrl) -- (buf.control)
    (buf.output) -- (o);
\end{tikzpicture}%

Full code:

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning, circuits.logic.US}

\makeatletter%
%
%
\pgfdeclareshape{tri state buffer active high}{
    \inheritsavedanchors[from=buffer gate US]
    \inheritanchorborder[from=buffer gate US]
    \inheritanchor[from=buffer gate US]{center}
    \inheritanchor[from=buffer gate US]{base}
    \inheritanchor[from=buffer gate US]{base west}
    \inheritanchor[from=buffer gate US]{base east}
    \inheritanchor[from=buffer gate US]{mid}
    \inheritanchor[from=buffer gate US]{mid west}
    \inheritanchor[from=buffer gate US]{mid east}
    \inheritanchor[from=buffer gate US]{north}
    \inheritanchor[from=buffer gate US]{north west}
    \inheritanchor[from=buffer gate US]{north east} 
    \inheritanchor[from=buffer gate US]{south}
    \inheritanchor[from=buffer gate US]{south east}
    \inheritanchor[from=buffer gate US]{south west}
    \inheritanchor[from=buffer gate US]{west}
    \inheritanchor[from=buffer gate US]{east}
    \inheritanchor[from=buffer gate US]{input}
    \inheritanchor[from=buffer gate US]{output}
    \anchor{control}{%
        \dimensions
        \pgfpointintersectionoflines{\csname pgf@anchor@buffer gate US@north west\endcsname}{\tipanchor}{\centerpoint}{\centerpoint\advance\pgf@y1pt}%
    }%
    \backgroundpath{%
        \dimensions%
        \pgf@xc\halfwidth%
        \pgf@yc\halfheight%
        \advance\pgf@xc-\outerxsep%
        \advance\pgf@yc-\outerysep%
        {%
            \pgftransformshift{\centerpoint}%
            \pgfpathmoveto{\tipanchor}%
            \pgfpathlineto{\pgfqpoint{-.833333\pgf@xc}{1.166666\pgf@yc}}%
            \pgfpathlineto{\pgfqpoint{-.833333\pgf@xc}{-1.166666\pgf@yc}}%
            \pgfpathclose%
            %
            % Draw the input.
            %
            \expandafter\ifx\expandafter\pgf@lib@sh@itext\csname input-1\endcsname%
                {%
                    \pgfpathcircle{%
                        \pgf@xa\halfside%
                        \pgf@x-.833333\pgf@xa%
                        \advance\pgf@x-.5\pgflinewidth%
                        \advance\pgf@x-\invertedradius%
                        \pgf@y0pt%
                    }{+\invertedradius}%                
                }%
            \fi%                
        }%
    }%
}

\pgfdeclareshape{tri state buffer active low}{
    \inheritsavedanchors[from=buffer gate US]
    \inheritanchorborder[from=buffer gate US]
    \inheritanchor[from=buffer gate US]{center}
    \inheritanchor[from=buffer gate US]{base}
    \inheritanchor[from=buffer gate US]{base west}
    \inheritanchor[from=buffer gate US]{base east}
    \inheritanchor[from=buffer gate US]{mid}
    \inheritanchor[from=buffer gate US]{mid west}
    \inheritanchor[from=buffer gate US]{mid east}
    \inheritanchor[from=buffer gate US]{north}
    \inheritanchor[from=buffer gate US]{north west}
    \inheritanchor[from=buffer gate US]{north east} 
    \inheritanchor[from=buffer gate US]{south}
    \inheritanchor[from=buffer gate US]{south east}
    \inheritanchor[from=buffer gate US]{south west}
    \inheritanchor[from=buffer gate US]{west}
    \inheritanchor[from=buffer gate US]{east}
    \inheritanchor[from=buffer gate US]{input}
    \inheritanchor[from=buffer gate US]{output}
    \anchor{control}{%
        \dimensions
        \tipanchor%
        \pgf@xa\pgf@x%  
        \pgf@ya\pgf@y%
        \csname pgf@anchor@buffer gate US@north west\endcsname%
        \advance\pgf@xa-\pgf@x%
        \advance\pgf@ya-\pgf@y%
        \pgfpointintersectionoflines{\csname pgf@anchor@buffer gate US@north west\endcsname}{\tipanchor}{\centerpoint}{\centerpoint\advance\pgf@y2pt}%
        \pgfmathparse{sqrt(\pgf@xa^2+\pgf@ya^2)/\pgf@xa*\invertedradius}
        \advance\pgf@y\pgfmathresult pt
        \advance\pgf@y\invertedradius
    }%
    \backgroundpath{%
        \dimensions%
        \pgf@xc\halfwidth%
        \pgf@yc\halfheight%
        \advance\pgf@xc-\outerxsep%
        \advance\pgf@yc-\outerysep%
        {%
            \pgftransformshift{\centerpoint}%
            \pgfpathmoveto{\tipanchor}%
            \pgfpathlineto{\pgfqpoint{-.833333\pgf@xc}{1.166666\pgf@yc}}%
            \pgfpathlineto{\pgfqpoint{-.833333\pgf@xc}{-1.166666\pgf@yc}}%
            \pgfpathclose%
            %
            % Draw the input.
            %
            \pgfpathcircle{%
                \tipanchor%
                \pgf@xa\pgf@x%  
                \pgf@ya\pgf@y%
                \csname pgf@anchor@buffer gate US@north west\endcsname%
                \advance\pgf@xa-\pgf@x%
                \advance\pgf@ya-\pgf@y%
                \pgfpointintersectionoflines{\csname pgf@anchor@buffer gate US@north west\endcsname}{\tipanchor}{\centerpoint}{\centerpoint\advance\pgf@y1pt}%
                \pgfmathparse{sqrt(\pgf@xa^2+\pgf@ya^2)/\pgf@xa*\invertedradius}
        \advance\pgf@y\pgfmathresult pt
                }{+\invertedradius}%
            \expandafter\ifx\expandafter\pgf@lib@sh@itext\csname input-1\endcsname%
                {%
                    \pgfpathcircle{%
                        \pgf@xa\halfside%
                        \pgf@x-.833333\pgf@xa%
                        \advance\pgf@x-.5\pgflinewidth%
                        \advance\pgf@x-\invertedradius%
                        \pgf@y0pt%
                    }{+\invertedradius}%                
                }%
            \fi%                
        }%
    }%
}

\tikzset{
    circuit declare symbol=tri state buffer active low,
    set tri state buffer active low graphic={draw, shape=tri state buffer active low, minimum size=5mm},
    circuit declare symbol=tri state buffer active high,
    set tri state buffer active high graphic={draw,shape=tri state buffer active high,minimum size=5mm}
}

\begin{document}

%
\begin{tikzpicture}[circuit logic US, on grid]
\node (i) {x};
\node (buf) [right of=i, tri state buffer active high] {};
\node (ctrl) [above=of buf] {c};
\node (o) [right of=buf] {y};

\draw (i) -- (buf.input)
    (ctrl) -- (buf.control)
    (buf.output) -- (o);
\end{tikzpicture}%

\begin{tikzpicture}[circuit logic US, on grid]
\node (i) {x};
\node (buf) [right of=i, tri state buffer active low] {};
\node (ctrl) [above=1 of buf] {c};
\node (o) [right of=buf] {y};

\draw (i) -- (buf.input)
    (ctrl) -- (buf.control)
    (buf.output) -- (o);
\end{tikzpicture}%
\end{document}