├── docs └── images │ ├── Gates.png │ ├── Examples.png │ ├── Gates_Tab.png │ ├── LatchTypes.png │ ├── Latch_Tab.png │ ├── Gates_scale.png │ ├── InputConfig.png │ ├── Latch_sizes.png │ ├── SignalLines.png │ ├── SignalTypes.png │ ├── BooleanCommands.png │ ├── Example_circuit.png │ ├── Examples_white.png │ ├── InputConfig_01.png │ ├── SignalDirection.png │ ├── subTabSignals.png │ ├── Example_minterms.png │ ├── Latch_controlGate.png │ ├── subTabExpressions.png │ ├── Latch_outputSuppress.png │ ├── BooleanCommands_examples.png │ ├── Latch_asynchronousInputs.png │ ├── Signals_and_expressions_Tab.png │ ├── Example_Synchonous_counter_2N.png │ ├── Example_shift_register_4bits.png │ ├── SignalLines.svg │ ├── InputConfig_01.svg │ ├── SignalDirection.svg │ ├── Latch_outputSuppress.svg │ ├── BooleanCommands_examples.svg │ └── InputConfig.svg ├── 0.9x ├── CircuitSymbolsLatexPreamble.tex ├── logicGates.inx └── logicGates.py ├── latest ├── logicGatesPreamble.tex └── logicGates.inx └── README.md /docs/images/Gates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Gates.png -------------------------------------------------------------------------------- /docs/images/Examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Examples.png -------------------------------------------------------------------------------- /docs/images/Gates_Tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Gates_Tab.png -------------------------------------------------------------------------------- /docs/images/LatchTypes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/LatchTypes.png -------------------------------------------------------------------------------- /docs/images/Latch_Tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Latch_Tab.png -------------------------------------------------------------------------------- /docs/images/Gates_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Gates_scale.png -------------------------------------------------------------------------------- /docs/images/InputConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/InputConfig.png -------------------------------------------------------------------------------- /docs/images/Latch_sizes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Latch_sizes.png -------------------------------------------------------------------------------- /docs/images/SignalLines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/SignalLines.png -------------------------------------------------------------------------------- /docs/images/SignalTypes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/SignalTypes.png -------------------------------------------------------------------------------- /docs/images/BooleanCommands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/BooleanCommands.png -------------------------------------------------------------------------------- /docs/images/Example_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Example_circuit.png -------------------------------------------------------------------------------- /docs/images/Examples_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Examples_white.png -------------------------------------------------------------------------------- /docs/images/InputConfig_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/InputConfig_01.png -------------------------------------------------------------------------------- /docs/images/SignalDirection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/SignalDirection.png -------------------------------------------------------------------------------- /docs/images/subTabSignals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/subTabSignals.png -------------------------------------------------------------------------------- /docs/images/Example_minterms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Example_minterms.png -------------------------------------------------------------------------------- /docs/images/Latch_controlGate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Latch_controlGate.png -------------------------------------------------------------------------------- /docs/images/subTabExpressions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/subTabExpressions.png -------------------------------------------------------------------------------- /docs/images/Latch_outputSuppress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Latch_outputSuppress.png -------------------------------------------------------------------------------- /docs/images/BooleanCommands_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/BooleanCommands_examples.png -------------------------------------------------------------------------------- /docs/images/Latch_asynchronousInputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Latch_asynchronousInputs.png -------------------------------------------------------------------------------- /docs/images/Signals_and_expressions_Tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Signals_and_expressions_Tab.png -------------------------------------------------------------------------------- /docs/images/Example_Synchonous_counter_2N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Example_Synchonous_counter_2N.png -------------------------------------------------------------------------------- /docs/images/Example_shift_register_4bits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsmMLK/inkscapeLogicGates/HEAD/docs/images/Example_shift_register_4bits.png -------------------------------------------------------------------------------- /0.9x/CircuitSymbolsLatexPreamble.tex: -------------------------------------------------------------------------------- 1 | \usepackage{amsmath,amsthm,amsbsy,amsfonts,amssymb} 2 | \usepackage[per=slash]{siunitx} 3 | \usepackage{steinmetz} 4 | \usepackage[utf8]{inputenc} 5 | %\usepackage[T1]{fontenc} 6 | 7 | \newcommand{\micro}{\ensuremath{\mu}} 8 | \newcommand{\phasorName}[1]{ \ensuremath{ \boldsymbol{\hat #1} } } 9 | \newcommand{\impedance}[1]{ \ensuremath{ \boldsymbol{#1} } } 10 | \newcommand{\complexPol}[2]{\ensuremath{#1\phase{#2}}} 11 | \newcommand{\complexPolDeg}[2]{\ensuremath{#1\phase{#2\degree}}} 12 | 13 | % new units 14 | \newunit{\Vef}{\volt_{ef}} % volt eficaz 15 | \newunit{\Vrms}{\volt_{rms}} % volt RMS 16 | \newunit{\Vpp}{\volt_{pp}} % volt peak-to-peak 17 | 18 | \newunit{\Aef}{\ampere_{ef}} % ampere eficaz 19 | \newunit{\Arms}{\ampere_{rms}} % ampere rms 20 | \newunit{\App}{\ampere_{pp}} % ampere peak-to-peak 21 | 22 | % logic Commands 23 | \newcommand{\NOT}[1]{\ensuremath{\overline{\mbox{\ensuremath{#1}}}}} 24 | \newcommand{\AND}{\ensuremath{\cdot}} 25 | \newcommand{\OR}{\ensuremath{+}} 26 | \newcommand{\XOR}{\ensuremath{\oplus}} 27 | \newcommand{\XNOR}{\ensuremath{\odot}} -------------------------------------------------------------------------------- /latest/logicGatesPreamble.tex: -------------------------------------------------------------------------------- 1 | \usepackage{amsmath,amsthm,amsbsy,amsfonts,amssymb} 2 | \usepackage[per-mode=symbol]{siunitx} 3 | \usepackage{steinmetz} 4 | \usepackage[utf8]{inputenc} 5 | %\usepackage[T1]{fontenc} 6 | 7 | \newcommand{\micro}{\ensuremath{\mu}} 8 | \newcommand{\phasorName}[1]{ \ensuremath{ \boldsymbol{\hat #1} } } 9 | \newcommand{\impedance}[1]{ \ensuremath{ \boldsymbol{#1} } } 10 | \newcommand{\complexPol}[2]{\ensuremath{#1\phase{#2}}} 11 | \newcommand{\complexPolDeg}[2]{\ensuremath{#1\phase{#2\degree}}} 12 | 13 | % new units 14 | \DeclareSIUnit{\Vef}{\volt_{ef}} % volt eficaz 15 | \DeclareSIUnit{\Vrms}{\volt_{rms}} % volt RMS 16 | \DeclareSIUnit{\Vpp}{\volt_{pp}} % volt peak-to-peak 17 | 18 | \DeclareSIUnit{\Aef}{\ampere_{ef}} % ampere eficaz 19 | \DeclareSIUnit{\Arms}{\ampere_{rms}} % ampere rms 20 | \DeclareSIUnit{\App}{\ampere_{pp}} % ampere peak-to-peak 21 | 22 | % logic Commands 23 | \newcommand{\NOT}[1]{\ensuremath{\overline{\mbox{\ensuremath{#1}}}}} 24 | \newcommand{\AND}{\ensuremath{\cdot}} 25 | \newcommand{\OR}{\ensuremath{+}} 26 | \newcommand{\XOR}{\ensuremath{\oplus}} 27 | \newcommand{\XNOR}{\ensuremath{\odot}} -------------------------------------------------------------------------------- /0.9x/logicGates.inx: -------------------------------------------------------------------------------- 1 | 2 | 3 | <_name>Logic Gates 4 | fsmMLK.logicGates 5 | logicGates.py 6 | inkscapeMadeEasy_Base.py 7 | inkscapeMadeEasy_Draw.py 8 | inkex.py 9 | 10 | 11 | Gate selection 12 | 1 13 | 0 14 | 0 15 | 0 16 | 0 17 | 0 18 | 0 19 | 20 | Input signal configuration (does not affect NOT gate) 21 | 2 22 | 1,1 23 | <_param name="instructions" type="description" xml:space="preserve">1: regular input 24 | 0: inverted input 25 | Ex: 0,1,1 (3 inputs) 26 | Top input is inverted, the others are regular 27 | 28 | 29 | 30 | <_option value="SRnor">SR postive (NOR) 31 | <_option value="SRnand">SR negative (NAND) 32 | <_option value="D">D 33 | <_option value="JK">JK 34 | <_option value="T">T 35 | 36 | 37 | 38 | <_option value="large">Large 39 | <_option value="medium">Medium 40 | <_option value="small">Small 41 | 42 | 43 | 0 44 | 0 45 | 46 | 47 | <_option value="none">None 48 | <_option value="level">Level (Latch) 49 | <_option value="edge">Edge (Flip-flop) 50 | 51 | 52 | <_option value="HIGH">high (or rising edge) 53 | <_option value="LOW">low (or falling edge) 54 | 55 | 56 | Asynchronous inputs 57 | 58 | <_option value="0">None 59 | <_option value="1">Active HIGH 60 | <_option value="-1">Active LOW 61 | 62 | 63 | 64 | <_option value="0">None 65 | <_option value="1">Active HIGH 66 | <_option value="-1">Active LOW 67 | 68 | 69 | 70 | 71 | Signals 72 | 73 | 0 74 | 75 | <_option value="custom">Custom 76 | <_option value="GND">GND 77 | <_option value="common">common 78 | <_option value="CLK">CLK 79 | <_option value="EN">EN 80 | <_option value="CLKi">NOT{CLK} 81 | <_option value="ENi">NOT{EN} 82 | <_option value="+vcc">+Vcc 83 | <_option value="-vcc">-Vcc 84 | <_option value="+5V">+5V 85 | <_option value="-5V">-5V 86 | <_option value="+15V">+15V 87 | <_option value="-15V">-15V 88 | 89 | A 90 | 91 | <_option value="0">North 92 | <_option value="90">West 93 | <_option value="-90">East 94 | <_option value="180">South 95 | 96 | 1 97 | 98 | Boolean expressions 99 | 100 | 0 101 | A \AND B 102 | <_param name="instructions" type="description" xml:space="preserve"> 103 | Valid commands: 104 | \AND, \OR, \XOR, XNOR : no arguments needed 105 | \NOT{...} : requires one argument 106 | 107 | 108 | 109 | 110 | 111 | all 112 | 113 | 114 | 115 | 116 | 117 | 118 | 121 | 122 | -------------------------------------------------------------------------------- /docs/images/SignalLines.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 41 | 44 | 45 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 63 | 69 | 72 | 79 | 85 | 86 | 105 | 118 | 124 | 127 | 134 | 135 | 154 | 155 | -------------------------------------------------------------------------------- /docs/images/InputConfig_01.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 42 | 43 | 45 | 52 | 58 | 59 | 66 | 72 | 73 | 74 | 76 | 77 | 79 | image/svg+xml 80 | 82 | 83 | 84 | 85 | 86 | 90 | 96 | 99 | 105 | 111 | 124 | 125 | 128 | 134 | 137 | 143 | 150 | 151 | 152 | 158 | 159 | 164 | regular input 175 | 181 | 182 | 187 | inverted input 198 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /latest/logicGates.inx: -------------------------------------------------------------------------------- 1 | 2 | 3 | Logic Gates 4 | fsmMLK.logicGates 5 | logicGates.py 6 | inkscapeMadeEasy/inkscapeMadeEasy_Base.py 7 | inkscapeMadeEasy/inkscapeMadeEasy_Draw.py 8 | 9 | 10 | 11 | 12 | 13 | true 14 | false 15 | 16 | 17 | 18 | false 19 | false 20 | 21 | 22 | 23 | false 24 | false 25 | 26 | 27 | 28 | false 29 | false 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 2 38 | 1,1,0 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | false 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | A 121 | true 122 | 123 | 124 | 125 | 126 | A \AND B 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | all 139 | 140 | 141 | 142 | 143 | 144 | 145 | 148 | 149 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logicGates 2 | 3 | This extension will assist you creating latches, flip-flops and logic gates following the 'distinctive shape' of IEEE Std 91/91a-1991 standard in [Inkscape](https://inkscape.org/). 4 | 5 | 6 | 7 | 8 | **TIP:** If you want to create timing diagrams, please take a look at my newest project [wavedromScape](https://github.com/fsmMLK/wavedromScape) 9 | 10 | 11 | ## Main features 12 | 13 | The main features of this extension are 14 | 15 | - You can use up to six inputs for each gate (except NOT and BUFFER gates) 16 | - Each input can be set to be inverted (negated) individually 17 | - Latch and flip-flop generator, with customizable optional control gates and asynchronous Preset and Clear. 18 | - Signal labeling generator with a few pre-defined commonly used signals 19 | - Boolean expression editor, with optional LaTeX support and predefined logic operator functions. 20 | 21 | ## Current and older versions 22 | 23 | Compatibility table 24 | 25 | | Inkscape | logicGates | inkscapeMadeEasy | Receive updates?| 26 | |------------------|-----------------|------------------|-----------------| 27 | | 1.0 | 1.0 (latest) | 1.0 (latest) | YES | 28 | | 0.48, 0.91, 0.92 | 0.9x (obsolete) | 0.9x (obsolete) | NO | 29 | 30 | 31 | **Latest version:** The latest version of **logicGates** is **1.0**. This version is compatible with Inkscape 1.0 and up only. It is **incompatible** with older Inkscape versions! 32 | 33 | **Older versions:** If you have an older version of Inkscape, please use the files under the folder **0.9x** on Github. 34 | 35 | **Important: Only the latest version will receive updates, new features, and bug fixes! The usage section in this documentation describes the latest version. In older versions, the disposition of the elements in the plugin's screen might be different. Some features might not be present or have different behavior.** 36 | 37 | # Installation and requirements 38 | 39 | Installation procedures for latest and older versions are described below. 40 | 41 | ## Requirements (all versions) 42 | 43 | - You will need [inkscapeMadeEasy](https://github.com/fsmMLK/inkscapeMadeEasy) plugin installed. Check the compatibility table above to know the version you need. 44 | 45 | ## Installation procedure (v1.0 only) 46 | 47 | **logicGates** was developed using Inkscape 1.0 in Linux (Kubuntu 18.04). It should work in different OSs too as long as all requirements are met. 48 | 49 | 1. Install [inkscapeMadeEasy](https://github.com/fsmMLK/inkscapeMadeEasy), **version 1.0** (latest). Follow the instructions in the manual page. **Note:** LaTeX text is used in **logicGates** if the support is activated (nicer results), otherwise regular text elements will be used. 50 | 51 | 2. **logicGates** installation 52 | 53 | 1. Go to Inkscape's extension directory with a file browser. Your inkscape extension directory can be accessed by opening Inkscape and selecting ``Edit > Preferences > System``. Look for the item **User Extensions** field. There is a button on the right of the field that will open a file explorer window in that specific folder. 54 | 55 | 2. Create a subfolder in the extension directory with the name ``logicGates``. **Important:** Be careful with upper and lower case letters. You must write as presented above. 56 | 57 | 3. Download **logicGates** files and place them inside the directory you just created. 58 | 59 | You don't have to copy all files from Github. The files you will need are `logicGates.py`, `logicGates.inx`, and `logicGatesPreamble.tex`. **You can find these files inside the ``latest`` folder**. In the end you must have the following files and directories in your Inkscape extension directory. 60 | 61 | **LaTeX users:** the file `logicGatesPreamble.tex` contains the macros defined in this plugin. You can add your own macros to this file. You can also add macros to ``inkscapeMadeEasy/basicLatexPackages.tex``. In this case the same macros will be accessible by all plugins that employ inkscapeMadeEasy. 62 | 63 | ``` 64 | inkscape 65 | ┣━━ extensions 66 | ┋ ┣━━ inkscapeMadeEasy <-- inkscapeMadeEasy folder 67 | ┃ ┣━━ inkscapeMadeEasy_Base.py 68 | ┃ ┣━━ inkscapeMadeEasy_Draw.py 69 | ┃ ┣━━ inkscapeMadeEasy_Plot.py 70 | ┃ ┗━━ basicLatexPackages.tex 71 | ┃ 72 | ┣━━ textext <-- texText folder (if you installed textText) 73 | ┃ ┋ 74 | ┃ 75 | ┣━━ logicGates <-- logicGates folder 76 | ┋ ┣━━ logicGatesPreamble.tex 77 | ┣━━ logicGates.py 78 | ┗━━ logicGates.inx 79 | 80 | NOTE: You might have other sub folders inside the extensions directory. They don't interfere with the plugin. 81 | ``` 82 | 83 | ## Installation procedure (v0.9x only) 84 | 85 | **logicGates** was developed using Inkscape 0.48 and 0.91 in Linux (Kubuntu 18.04). It should work in different OSs too as long as all requirements are met. 86 | 87 | 1. Install [inkscapeMadeEasy](https://github.com/fsmMLK/inkscapeMadeEasy), **version 1.0** (latest). Follow the instructions in the manual page. **Note:** LaTeX text is used in **logicGates** if the support is activated (nicer results), otherwise regular text elements will be used. 88 | 89 | 2. **logicGates** installation 90 | 91 | 1. Go to Inkscape's extension directory with a file browser. 92 | 93 | 2. Download **logicGates** files and place them inside the directory you just created. 94 | 95 | You don't have to copy all files from Github. The files you will need are `logicGates.py`, `logicGates.inx`, and `CircuitSymbolsLatexPreamble.tex`. **You can find these files inside the ``0.9x`` folder**. In the end you must have the following files and directories in your Inkscape extension directory. 96 | 97 | ``` 98 | inkscape 99 | ┣━━ extensions 100 | ┋ ┣━━ inkscapeMadeEasy_Base.py 101 | ┣━━ inkscapeMadeEasy_Draw.py 102 | ┣━━ inkscapeMadeEasy_Plot.py 103 | ┃ 104 | ┣━━ textextLib 105 | ┃ ┣━━ __init__.py 106 | ┃ ┣━━ basicLatexPackages.tex 107 | ┃ ┣━━ CircuitSymbolsLatexPreamble.tex <-- from repository folder 0.9x! 108 | ┃ ┣━━ textext.inx 109 | ┃ ┗━━ textext.py 110 | ┃ 111 | ┣━━ logicGates.py <-- from repository folder 0.9x! 112 | ┣━━ logicGates.inx <-- from repository folder 0.9x! 113 | ┋ 114 | ``` 115 | 116 | # Usage 117 | 118 | The extension can be found under `extensions > fsmMLK > Circuit symbols` menu. 119 | 120 | This extension is presented in three tabs. The **Logic gates** and **Latch and F.F.** tabs allow you to create logic gates and latches/flip-flops respectively, while **Signals and Expressions** create boolean expressions and logic signal labels. 121 | 122 | ## Logic Gates tab 123 | 124 | 125 | 126 | **Gate checkboxes:** You can select the gates. More than one gate can be created at once, however they will share the same input configuration (see below). 127 | 128 | 129 | 130 | **Symbol size:** You can select between 2 sizes, presented below. 131 | 132 | 133 | 134 | **Number of inputs:** Number of inputs of the gate. This parameter does not affect NOT and BUFFER gates. You can choose any number between 2 and 6. 135 | 136 | **Input config:** You can select whether the inputs must be inverted. This field accepts a sequence of values `1` or `0`. You can create a sequence of 1s and 0s without any spaces, with spaces or commas. 137 | 138 | - 1 stands for regular input 139 | - 0 stands for inverted input 140 | 141 | 142 | 143 | The first element of the sequence is associated to the input at the top. If this string has less elements than the number of inputs, the remaining inputs will be set to regular inputs. 144 | 145 | Examples: 146 | 147 | 148 | 149 | 150 | ## Latch and F.F. tab 151 | 152 | 153 | 154 | **Type:** You can select the type of Latch/Flip-flop. 155 | 156 | 157 | 158 | **Symbol size:** You can select between 3 sizes, presented below. 159 | 160 | 161 | 162 | **Suppress Q and not{Q} outputs:** You can choose any output (Q and NOT{Q}) to be suppressed. 163 | 164 | 165 | 166 | **Control Gate type:** You can optionally include a control gate, by level (latch) or edge (flip-flop). Se image below. 167 | 168 | **Control Gate Activation Logic:** Here you can select the type of activation logic of the control gate. Se image below. 169 | 170 | - active on HIGH (latch) or rising edge ⮥ (flip-flop) 171 | - active on LOW (latch) or falling edge ⮧ (flip-flop) 172 | 173 | 174 | 175 | **Asynchronous Preset:** Add asynchronous Preset signal. You can select between active HIGH or LOW. 176 | 177 | **Asynchronous Clear:** Add asynchronous Clear signal. You can select between active HIGH or LOW. 178 | 179 | 180 | 181 | ## Signals and Expressions tab 182 | 183 | 184 | 185 | This tab is presented in two subtabs, *Signals* and *Expressions*. The first create signal nodes to add to your logic circuit. The second creates a text element with a boolean expression. The 'Apply' button will execute the action associated to the subtab that is on the top 186 | 187 | #### Signals subtab 188 | 189 | 190 | 191 | **Signal type:** Allows the selection of one type of signal. You can select a few commonly used signals or select ``Custom`` to customize its label. (see below) 192 | 193 | 194 | 195 | **Direction:** Direction of the signal line. This option is used only if ``Draw signal line`` option is enabled. 196 | 197 | 198 | 199 | **Custom label:** Label of the signal. This option is used only if ``Custom`` or ``Digital`` is selected in `Signal type`. If LaTeX support is enabled the text will be inserted in a mathematical environment $...$ 200 | 201 | 202 | **Draw signal line:** signal line toggle. 203 | 204 | 205 | 206 | #### Expressions subtab 207 | 208 | 209 | 210 | **Boolean expression:** Boolean expression area. Predefined commands were created for the basic boolean operators: 211 | 212 | 213 | 214 | > Note: The command ``\NOT`` has one argument and **MUST** be enclosed between ``{ }`` 215 | 216 | Examples: 217 | 218 | 219 | 220 | 221 | # Observations 222 | 223 | - The objects will be created in the center of your screen. 224 | 225 | # Examples 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /docs/images/SignalDirection.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 40 | 43 | 44 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 62 | 75 | 77 | 81 | 84 | 91 | 97 | 98 | 117 | North 128 | 129 | 132 | 136 | 139 | 146 | 152 | 153 | 172 | West 183 | 184 | 187 | 191 | 194 | 201 | 207 | 208 | 227 | East 238 | 239 | 241 | 245 | 248 | 255 | 261 | 262 | 281 | South 292 | 293 | 294 | -------------------------------------------------------------------------------- /docs/images/Latch_outputSuppress.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 41 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 59 | Q Suppressed 69 | NOT Q suppressed 79 | 83 | 93 | 96 | 100 | 106 | 107 | 132 | 135 | 138 | 144 | 145 | 168 | 171 | 174 | 180 | 181 | 200 | 203 | 206 | 212 | 213 | 232 | 233 | 237 | 247 | 250 | 254 | 260 | 261 | 280 | 283 | 286 | 292 | 293 | 316 | 319 | 322 | 328 | 329 | 348 | 351 | 354 | 360 | 361 | 380 | 381 | 382 | -------------------------------------------------------------------------------- /docs/images/BooleanCommands_examples.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 40 | 43 | 44 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 62 | \NOT{(A\AND B)}\XOR C 121 | \NOT{(A\OR B)\XNOR C} 184 | \NOT{(A\OR \NOT{B})}\AND \NOT{\NOT{C}} 261 | 269 | 277 | 285 | 293 | 299 | 300 | -------------------------------------------------------------------------------- /docs/images/InputConfig.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 42 | 43 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 61 | 67 | 70 | 76 | 82 | 95 | 96 | 99 | 105 | 111 | 112 | 118 | 119 | 125 | 128 | 134 | 140 | 153 | 154 | 157 | 163 | 169 | 172 | 178 | 185 | 186 | 187 | 193 | 194 | 200 | 203 | 209 | 215 | 228 | 229 | 232 | 235 | 241 | 248 | 249 | 255 | 258 | 264 | 271 | 272 | 275 | 281 | 288 | 289 | 290 | 296 | 297 | 303 | 306 | 312 | 318 | 331 | 332 | 335 | 338 | 344 | 351 | 352 | 358 | 364 | 370 | 373 | 379 | 386 | 387 | 388 | 394 | 395 | 401 | 404 | 410 | 416 | 429 | 430 | 433 | 439 | 442 | 448 | 455 | 456 | 459 | 465 | 472 | 473 | 479 | 482 | 488 | 495 | 496 | 499 | 505 | 512 | 513 | 514 | 520 | 521 | 1,0,0,1,0,0 534 | 0,1,1,1,0 547 | 0,1,0,0 560 | 1,1,0 573 | 1,1 586 | 594 | 602 | 610 | 618 | N=6 631 | N=5 644 | N=4 657 | N=3 670 | N=2 683 | 684 | -------------------------------------------------------------------------------- /0.9x/logicGates.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import math 4 | import os 5 | 6 | import inkscapeMadeEasy_Base as inkBase 7 | import inkscapeMadeEasy_Draw as inkDraw 8 | 9 | 10 | # --------------------------------------------- 11 | # noinspection PyUnboundLocalVariable,PyDefaultArgument,PyAttributeOutsideInit 12 | class LogicGates(inkBase.inkscapeMadeEasy): 13 | def __init__(self): 14 | inkBase.inkscapeMadeEasy.__init__(self) 15 | 16 | self.OptionParser.add_option("--tab", action="store", type="string", dest="tab", default="object") 17 | 18 | self.OptionParser.add_option("--ANDgate", action="store", type="inkbool", dest="ANDgate", default=False) 19 | self.OptionParser.add_option("--ORgate", action="store", type="inkbool", dest="ORgate", default=False) 20 | self.OptionParser.add_option("--XORgate", action="store", type="inkbool", dest="XORgate", default=False) 21 | self.OptionParser.add_option("--NOTgate", action="store", type="inkbool", dest="NOTgate", default=False) 22 | self.OptionParser.add_option("--NANDgate", action="store", type="inkbool", dest="NANDgate", default=False) 23 | self.OptionParser.add_option("--NORgate", action="store", type="inkbool", dest="NORgate", default=False) 24 | self.OptionParser.add_option("--XNORgate", action="store", type="inkbool", dest="XNORgate", default=False) 25 | 26 | self.OptionParser.add_option("--nInput", action="store", type="int", dest="nInput", default=2) 27 | self.OptionParser.add_option("--InputTypes", action="store", type="string", dest="InputTypes", default='11') 28 | 29 | self.OptionParser.add_option("--latchType", action="store", type="string", dest="latchType", default='none') 30 | self.OptionParser.add_option("--latchSize", action="store", type="string", dest="latchSize", default='large') 31 | self.OptionParser.add_option("--latchSuppressq", action="store", type="inkbool", dest="latchSuppressq", default=False) 32 | self.OptionParser.add_option("--latchSuppressNOTq", action="store", type="inkbool", dest="latchSuppressNOTq", default=False) 33 | 34 | self.OptionParser.add_option("--latchGate", action="store", type="string", dest="latchGate", default='none') 35 | self.OptionParser.add_option("--latchGateLogic", action="store", type="string", dest="latchGateLogic", default='HIGH') 36 | self.OptionParser.add_option("--latchPreset", action="store", type="string", dest="latchPreset", default='0') 37 | self.OptionParser.add_option("--latchClear", action="store", type="string", dest="latchClear", default='0') 38 | 39 | self.OptionParser.add_option("--flagSignal", action="store", type="inkbool", dest="flagSignal", default=False) 40 | self.OptionParser.add_option("--signal", action="store", type="string", dest="signal", default='GND') 41 | self.OptionParser.add_option("--signalVal", action="store", type="string", dest="signalVal", default='E') 42 | self.OptionParser.add_option("--signalRot", action="store", type="float", dest="signalRot", default=0) 43 | self.OptionParser.add_option("--signalDrawLine", action="store", type="inkbool", dest="signalDrawLine", default=True) 44 | 45 | self.OptionParser.add_option("--flagExpression", action="store", type="inkbool", dest="flagExpression", default=False) 46 | self.OptionParser.add_option("--boolExpression", action="store", type="string", dest="boolExpression", default='') 47 | 48 | self.lineStyle = inkDraw.lineStyle.setSimpleBlack() 49 | self.lineStyleBody = inkDraw.lineStyle.setSimpleBlack(1.8) 50 | self.totalHeight = 30 # total height of the logic gate 51 | self.totalWidth = 50 # total width of the logic gate, including in/output 52 | self.lengthTerm = 10 # length of the terminals 53 | 54 | def effect(self): 55 | 56 | so = self.options 57 | 58 | # sets the position to the viewport center, round to next 10. 59 | position = [self.view_center[0], self.view_center[1]] 60 | position[0] = int(math.ceil(position[0] / 10.0)) * 10 61 | position[1] = int(math.ceil(position[1] / 10.0)) * 10 62 | 63 | # root_layer = self.current_layer 64 | root_layer = self.document.getroot() 65 | # root_layer = self.getcurrentLayer() 66 | 67 | so.tab = so.tab.replace('"', '') # removes de exceding double quotes from the string 68 | 69 | # latex related preamble 70 | self.preambleFile = os.getcwd() + '/textextLib/CircuitSymbolsLatexPreamble.tex' 71 | 72 | self.fontSize = 6.0 73 | self.fontSizeSmall = self.fontSize * 0.7 74 | self.textOffset = self.fontSize / 1.5 # offset between symbol and text 75 | self.textOffsetSmall = self.fontSizeSmall / 2 # offset between symbol and text 76 | self.textStyle = inkDraw.textStyle.setSimpleBlack(self.fontSize, justification='center') 77 | self.textStyleSmall = inkDraw.textStyle.setSimpleBlack(self.fontSizeSmall, justification='center') 78 | 79 | # -------------------------- 80 | # Gates 81 | # --------------------------- 82 | 83 | if so.tab == 'Gates': 84 | 85 | N_input = so.nInput 86 | inputVector = [True] * N_input 87 | 88 | # vector with type of inputs (regular or inverted) 89 | so.InputTypes = so.InputTypes.replace(' ', '').replace(',', '') 90 | for i in range(min(N_input, len(so.InputTypes))): 91 | if so.InputTypes[i] == '0': 92 | inputVector[i] = False 93 | 94 | if so.ANDgate: 95 | self.createAND(root_layer, inputVector, True, position) 96 | if so.NANDgate: 97 | self.createAND(root_layer, inputVector, False, position) 98 | 99 | if so.ORgate: 100 | self.createOR(root_layer, inputVector, True, position) 101 | if so.NORgate: 102 | self.createOR(root_layer, inputVector, False, position) 103 | 104 | if so.XORgate: 105 | self.createXOR(root_layer, inputVector, True, position) 106 | if so.XNORgate: 107 | self.createXOR(root_layer, inputVector, False, position) 108 | 109 | if so.NOTgate: 110 | self.createNOT(root_layer, position) 111 | 112 | # -------------------------- 113 | # Latches and Flip-flops 114 | # --------------------------- 115 | 116 | if so.tab == 'Latches': 117 | if so.latchGateLogic == 'HIGH': 118 | logic = True 119 | else: 120 | logic = False 121 | self.createLatch(root_layer, position, type=so.latchType, controlGate=so.latchGate, controlGateLogic=logic, 122 | asynPreset=int(so.latchPreset), asynClear=int(so.latchClear), size=so.latchSize, suppressq=so.latchSuppressq, 123 | suppressNOTq=so.latchSuppressNOTq) 124 | 125 | # -------------------------- 126 | # SignalsAndExpressions 127 | # --------------------------- 128 | if so.tab == 'SignalsAndExpressions': 129 | 130 | if so.flagExpression: 131 | if not inkDraw.useLatex: 132 | value = so.boolExpression.replace(' ', '').replace(r'\AND', '.').replace(r'\OR', '+').replace('\XOR', u'\u2295') 133 | value = value.replace('\XNOR', u'\u2299').replace(r'\NOT', u'\u00AC').replace('{', '(').replace('}', ')') # removes LaTeX stuff 134 | else: 135 | value = '$' + so.boolExpression + '$' 136 | 137 | inkDraw.text.latex(self, root_layer, value, [position[0], position[1]], self.fontSize, refPoint='cc', preambleFile=self.preambleFile) 138 | 139 | if so.flagSignal: 140 | 141 | if so.signal == "GND": 142 | self.drawGND(root_layer, position, angleDeg=so.signalRot) 143 | return 144 | 145 | if so.signal == "common": 146 | self.drawCommon(root_layer, position, angleDeg=so.signalRot) 147 | return 148 | 149 | if so.signal == "custom": 150 | text = so.signalVal 151 | 152 | if so.signal == "+vcc": 153 | text = '+V_{cc}' 154 | 155 | if so.signal == "-vcc": 156 | text = '-V_{cc}' 157 | 158 | if so.signal == "+5V": 159 | text = r'+5\volt' 160 | 161 | if so.signal == "-5V": 162 | text = r'-5\volt' 163 | 164 | if so.signal == "+15V": 165 | text = r'+15\volt' 166 | 167 | if so.signal == "-15V": 168 | text = r'-15\volt' 169 | 170 | if so.signal == "EN": 171 | text = r'EN' 172 | 173 | if so.signal == "CLK": 174 | text = r'CLK' 175 | 176 | if so.signal == "ENi": 177 | text = r'\NOT{EN}' 178 | 179 | if so.signal == "CLKi": 180 | text = r'\NOT{CLK}' 181 | 182 | self.drawV(root_layer, position, angleDeg=so.signalRot, nodalVal=text, drawLine=so.signalDrawLine) 183 | return 184 | 185 | def createSignal(self, flagTrue, parent, position=[0, 0], direction='E', extraLength=0.0, label='input', name=None, fontSizeFactor=1.0, 186 | isClock=False): 187 | """ Creates signals to logic Gates (inputs or outputs) 188 | 189 | flagTrue: TRUE: regular input. FALSE: NOT input 190 | parent: parent object 191 | position: position [x,y] 192 | direction: orientation of the signal. Values possible: 'N', 'S', 'W', 'E' 193 | extraLength: add extra lenght to the input line. default: 0.0 194 | label: label of the object (it can be repeated) 195 | name: Name of the signal. In ``None`` (default) no name is added 196 | fontSizeFactor: font scale factor. Default: 1.0 197 | isClock: input is clock type. Default: False 198 | """ 199 | 200 | group = self.createGroup(parent, label) 201 | elem = self.createGroup(group, label) 202 | 203 | if flagTrue: 204 | inkDraw.line.relCoords(elem, [[-self.lengthTerm - extraLength, 0]], position, label, self.lineStyle) 205 | 206 | else: 207 | inkDraw.line.absCoords(elem, [[-5.5, 0], [-self.lengthTerm - extraLength, 0]], position, label, self.lineStyle) 208 | inkDraw.circle.centerRadius(elem, [-3, 0], 2, position, label, inkDraw.lineStyle.setSimpleBlack(1.2)) 209 | 210 | if isClock: 211 | inkDraw.line.absCoords(elem, [[0, -4], [4, 0], [0, 4]], position, label, inkDraw.lineStyle.setSimpleBlack(0.9)) 212 | 213 | if isClock: 214 | offsetText = self.textOffset * fontSizeFactor + 4 215 | else: 216 | offsetText = self.textOffset * fontSizeFactor 217 | 218 | if direction == 'N': 219 | self.rotateElement(elem, position, -90) # y direction is inverted 220 | posText = [position[0], position[1] + offsetText] 221 | justif = 'tc' 222 | if direction == 'S': 223 | self.rotateElement(elem, position, 90) # y direction is inverted 224 | posText = [position[0], position[1] - offsetText] 225 | justif = 'bc' 226 | if direction == 'E': 227 | self.rotateElement(elem, position, 180) # y direction is inverted 228 | posText = [position[0] - offsetText, position[1]] 229 | justif = 'cr' 230 | if direction == 'W': 231 | posText = [position[0] + offsetText, position[1]] 232 | justif = 'cl' 233 | 234 | if name: 235 | inkDraw.text.latex(self, group, name, position=posText, fontSize=self.fontSize * fontSizeFactor, refPoint=justif, 236 | preambleFile=self.preambleFile) 237 | 238 | # --------------------------------------------- 239 | def createInput(self, flagTrue, parent, position=[0, 0], extraLength=0.0, label='input', name=None, fontSizeFactor=1.0): 240 | """ Creates input to logic Gates 241 | 242 | flagTrue: TRUE: regular input. FALSE: NOT input 243 | parent: parent object 244 | position: position [x,y] 245 | extraLength: add extra lenght to the input line. default: 0.0 246 | label: label of the object (it can be repeated) 247 | name: Name of the signal. In ``None`` (default) no name is added 248 | fontSizeFactor: font scale factor. Default: 1.0 249 | """ 250 | direction = 'W' 251 | self.createSignal(flagTrue, parent, position, direction, extraLength, label, name, fontSizeFactor) 252 | 253 | # --------------------------------------------- 254 | def createOutput(self, flagTrue, parent, position=[0, 0], extraLength=0.0, label='output', name=None, fontSizeFactor=1.0): 255 | """ Creates output to logic Gates 256 | 257 | flagTrue: TRUE: regular input. FALSE: NOT input 258 | parent: parent object 259 | position: position [x,y] 260 | extraLength: add extra lenght to the input line. default: 0.0 261 | label: label of the object (it can be repeated) 262 | name: Name of the signal. In ``None`` (default) no name is added 263 | fontSizeFactor: font scale factor. Default: 1.0 264 | """ 265 | direction = 'E' 266 | if flagTrue: 267 | self.createSignal(flagTrue, parent, [position[0], position[1]], direction, extraLength, label, name, fontSizeFactor) 268 | else: 269 | self.createSignal(flagTrue, parent, [position[0] - 0.5, position[1]], direction, extraLength + 0.5, label, name, fontSizeFactor) 270 | 271 | # --------------------------------------------- 272 | def drawANDBody(self, parent, position=[0, 0], label='BodyAND'): 273 | """ Creates body of AND logic Gate 274 | 275 | parent: parent object 276 | position: position [x,y] 277 | label: label of the object (it can be repeated) 278 | """ 279 | 280 | h = self.totalHeight / 2.0 # half height 281 | R = h # radius 282 | widthBase = self.totalWidth - 2 * self.lengthTerm - R # length of the straight part of AND body 283 | 284 | group = self.createGroup(parent, label) 285 | 286 | inkDraw.line.absCoords(group, [[0, h], [-widthBase, h], [-widthBase, -h], [0, -h]], position, label, self.lineStyleBody) 287 | inkDraw.arc.centerAngStartAngEnd(group, [0, 0], R, 90, -90, position, label, self.lineStyleBody, largeArc=True) 288 | 289 | # --------------------------------------------- 290 | def drawORBody(self, parent, position=[0, 0], label='BodyOR'): 291 | """ Creates body of OR logic Gate 292 | 293 | parent: parent object 294 | position: position [x,y] 295 | label: label of the object (it can be repeated) 296 | """ 297 | h = self.totalHeight / 2.0 # half height 298 | x = h + 5 # x distance of the tip to the center 299 | R = math.sqrt(((x * x - h * h) / (2 * h)) ** 2 + x * x) 300 | widthBase = self.totalWidth - 2 * self.lengthTerm - 15 # length of the straight part of AND body 301 | 302 | group = self.createGroup(parent, label) 303 | 304 | inkDraw.line.absCoords(group, [[0, h], [-widthBase, h]], position, label, self.lineStyleBody) 305 | inkDraw.line.absCoords(group, [[0, -h], [-widthBase, -h]], position, label, self.lineStyleBody) 306 | inkDraw.arc.startEndRadius(group, [x, 0], [0, h], R, position, label, self.lineStyleBody, flagRightOf=False, flagOpen=True) 307 | inkDraw.arc.startEndRadius(group, [0, -h], [x, 0], R, position, label, self.lineStyleBody, flagRightOf=False, flagOpen=True) 308 | inkDraw.arc.startEndRadius(group, [-widthBase, -h], [-widthBase, h], self.totalHeight, position, label, self.lineStyleBody, flagRightOf=False, 309 | flagOpen=True) 310 | 311 | # --------------------------------------------- 312 | 313 | def drawXORBody(self, parent, position=[0, 0], label='BodyXOR'): 314 | """ Creates body of XOR logic Gate 315 | 316 | parent: parent object 317 | position: position [x,y] 318 | label: label of the object (it can be repeated) 319 | """ 320 | h = self.totalHeight / 2.0 # half height 321 | x = h + 5 # x distance of the tip to the center 322 | R = math.sqrt(((x * x - h * h) / (2 * h)) ** 2 + x * x) 323 | space = 4 # space between parallel arcs 324 | widthBase = self.totalWidth - 2 * self.lengthTerm - 15 - space # length of the straight part of AND body 325 | 326 | group = self.createGroup(parent, label) 327 | 328 | inkDraw.line.absCoords(group, [[0, h], [-widthBase, h]], position, label, self.lineStyleBody) 329 | inkDraw.line.absCoords(group, [[0, -h], [-widthBase, -h]], position, label, self.lineStyleBody) 330 | inkDraw.arc.startEndRadius(group, [x, 0], [0, h], R, position, label, self.lineStyleBody, flagRightOf=False, flagOpen=True) 331 | inkDraw.arc.startEndRadius(group, [0, -h], [x, 0], R, position, label, self.lineStyleBody, flagRightOf=False, flagOpen=True) 332 | inkDraw.arc.startEndRadius(group, [-widthBase, -h], [-widthBase, h], self.totalHeight, position, label, self.lineStyleBody, flagRightOf=False, 333 | flagOpen=True) 334 | inkDraw.arc.startEndRadius(group, [-widthBase - space, -h], [-widthBase - space, h], self.totalHeight, position, label, self.lineStyleBody, 335 | flagRightOf=False, flagOpen=True) 336 | 337 | # --------------------------------------------- 338 | def drawInputOR(self, parent, vectorInput=[True, True], position=[0, 0], label='InputORGate'): 339 | """ Creates inputs to OR/NOR/XOR/XNOR logic Gates 340 | 341 | parent: parent object 342 | vectorInput: vector with booleans. Default [True,True] 343 | It's length is the number of inputs of the gate. 344 | For each input (top to bottom) True: regular input False: Negated input. 345 | position: position [x,y] 346 | label: label of the object (it can be repeated) 347 | """ 348 | 349 | group = self.createGroup(parent, label) 350 | 351 | N_input = len(vectorInput) 352 | spaceBetweenInputs = 20.0 / (N_input - 1) 353 | r = self.totalHeight # radius 354 | H = self.totalHeight / 2.0 # total height 355 | h_max = 10 # maximum height of inputs 356 | 357 | for i in range(0, N_input): 358 | h = -(h_max - i * spaceBetweenInputs) # bottom to up because inkscape is upside down =( 359 | x = math.sqrt(r ** 2 - h ** 2) 360 | L0 = math.sqrt(r ** 2 - H ** 2) 361 | L = x - L0 362 | 363 | self.createInput(vectorInput[i], group, [L + position[0], h + position[1]], L - 2.5, 364 | 'input' + str(i)) # 2.5 for reducing a little the lengh so that AND and OR gates have the same width 365 | 366 | # --------------------------------------------- 367 | def drawInputAND(self, parent, vectorInput=[True, True], position=[0, 0], label='InputANDGate'): 368 | """ Creates inputs to AND,NAND logic Gates 369 | 370 | parent: parent object 371 | vectorInput: vector with booleans. Default [True,True] 372 | It's length is the number of inputs of the gate. 373 | For each input (top to bottom) True: regular input False: Negated input. 374 | position: position [x,y] 375 | label: label of the object (it can be repeated) 376 | """ 377 | 378 | group = self.createGroup(parent, label) 379 | 380 | N_input = len(vectorInput) 381 | spaceBetweenInputs = 20.0 / (N_input - 1) 382 | h_max = 10 # maximum height of inputs 383 | 384 | for i in range(0, N_input): 385 | h = -(h_max - i * spaceBetweenInputs) 386 | self.createInput(vectorInput[i], group, [position[0], h + position[1]], 0, 'input' + str(i)) 387 | 388 | # --------------------------------------------- 389 | def createAND(self, parent, vectorInput=[True, True], output=True, position=[0, 0], label='BodyAND'): 390 | """ Creates AND/NAND logic Gate 391 | 392 | parent: parent object 393 | vectorInput: vector with booleans. Default [True,True] 394 | It's length is the number of inputs of the gate. 395 | For each input (top to bottom) True: regular input False: Negated input. 396 | output: selects AND or NAND gate (Default True) 397 | True: AND 398 | False: NAND 399 | position: position [x,y] 400 | label: label of the object (it can be repeated) 401 | """ 402 | h = self.totalHeight / 2.0 # half height 403 | R = h # radius 404 | widthBase = self.totalWidth - 2 * self.lengthTerm - R # length of the straight part of AND body 405 | 406 | group = self.createGroup(parent, label) 407 | x_output = R # x coordinate of the output 408 | 409 | self.drawANDBody(group, position) 410 | self.drawInputAND(group, vectorInput, [-widthBase + position[0], position[1]]) 411 | self.createOutput(output, group, [x_output + position[0], position[1]]) 412 | 413 | # --------------------------------------------- 414 | def createOR(self, parent, vectorInput=[True, True], output=True, position=[0, 0], label='ORGate'): 415 | """ Creates OR/NOR logic Gate 416 | 417 | parent: parent object 418 | vectorInput: vector with booleans. Default [True,True] 419 | It's length is the number of inputs of the gate. 420 | For each input (top to bottom) True: regular input False: Negated input. 421 | output: selects OR or NOR gate (Default True) 422 | True: OR 423 | False: NOR 424 | position: position [x,y] 425 | label: label of the object (it can be repeated) 426 | """ 427 | 428 | group = self.createGroup(parent, label) 429 | x_output = self.totalHeight / 2.0 + 5 # x coordinate of the output 430 | 431 | self.drawORBody(group, position) 432 | self.drawInputOR(group, vectorInput, [position[0] - 15, position[1]]) 433 | self.createOutput(output, group, [x_output + position[0], position[1]], -2.5) # 2.5 for reducing a little the lengh so that AND and 434 | 435 | # --------------------------------------------- 436 | def createXOR(self, parent, vectorInput=[True, True], output=True, position=[0, 0], label='XORGate'): 437 | """ Creates XOR/XNOR logic Gate 438 | 439 | parent: parent object 440 | vectorInput: vector with booleans. Default [True,True] 441 | It's length is the number of inputs of the gate. 442 | For each input (top to bottom) True: regular input False: Negated input. 443 | output: selects OR or NOR gate (Default True) 444 | True: XOR 445 | False: XNOR 446 | position: position [x,y] 447 | label: label of the object (it can be repeated) 448 | """ 449 | 450 | group = self.createGroup(parent, label) 451 | x_output = self.totalHeight / 2.0 + 5 # x coordinate of the output 452 | 453 | self.drawXORBody(group, position) 454 | self.drawInputOR(group, vectorInput, [position[0] - 15, position[1]]) 455 | self.createOutput(output, group, [x_output + position[0], position[1]], -2.5) # 2.5 for reducing a little the lengh so that AND and 456 | 457 | # --------------------------------------------- 458 | 459 | def createNOT(self, parent, position=[0, 0], label='NOTGate'): 460 | """ Creates NOT logic Gate 461 | 462 | parent: parent object 463 | vectorInput: vector with booleans. Default [True,True] 464 | It's length is the number of inputs of the gate. 465 | For each input (top to bottom) True: regular input False: Negated input. 466 | position: position [x,y] 467 | label: label of the object (it can be repeated) 468 | """ 469 | 470 | triangleSide = 20 471 | triangle_height = triangleSide * math.sqrt(3) / 2 472 | 473 | group = self.createGroup(parent, label) 474 | inkDraw.line.absCoords(group, [[0, triangleSide / 2], [triangle_height, 0], [0, -triangleSide / 2], [0, triangleSide / 2]], position, 'not1', 475 | self.lineStyleBody, True) 476 | 477 | self.createInput([True], group, position) 478 | self.createOutput(False, group, [triangle_height + 0.5 + position[0], 0 + position[1]], 30 - triangle_height - 10 - 0.5) 479 | 480 | # --------------------------------------------- 481 | 482 | def drawV(self, parent, position=[0, 0], label='GND', angleDeg=0, nodalVal='V_{cc}', drawLine=True): 483 | """ draws a Voltage node 484 | 485 | parent: parent object 486 | position: position [x,y] 487 | label: label of the object (it can be repeated) 488 | angleDeg: rotation angle in degrees counter-clockwise (default 0) 489 | nodalVal: name of the node (default: 'V_{cc}') 490 | drawLine: draws line for connection (default: True) 491 | """ 492 | linestyleBlackFill = inkDraw.lineStyle.set(lineWidth=0.7, fillColor=inkDraw.color.defined('black')) 493 | group = self.createGroup(parent, label) 494 | elem = self.createGroup(group, label) 495 | 496 | inkDraw.circle.centerRadius(elem, position, 1.0, offset=[0, 0], lineStyle=linestyleBlackFill) 497 | if drawLine: 498 | inkDraw.line.relCoords(elem, [[0, 10]], position) 499 | 500 | # text 501 | if abs(angleDeg) <= 90: 502 | justif = 'bc' 503 | pos_text = [position[0], position[1] - self.textOffset] 504 | else: 505 | justif = 'tc' 506 | pos_text = [position[0], position[1] + self.textOffset] 507 | 508 | if not inkDraw.useLatex: 509 | value = nodalVal.replace('_', '').replace(r'\NOT', u'\u00AC').replace('{', '').replace('}', '').replace(r'\volt', 510 | 'V') # removes LaTeX stuff 511 | else: 512 | value = '$' + nodalVal + '$' 513 | temp = inkDraw.text.latex(self, group, value, pos_text, fontSize=self.fontSize, refPoint=justif, preambleFile=self.preambleFile) 514 | 515 | self.rotateElement(temp, position, -angleDeg) 516 | 517 | if angleDeg != 0: 518 | self.rotateElement(group, position, angleDeg) 519 | 520 | return group 521 | 522 | # --------------------------------------------- 523 | def drawGND(self, parent, position=[0, 0], label='GND', angleDeg=0): 524 | """ draws a GND 525 | 526 | parent: parent object 527 | position: position [x,y] 528 | label: label of the object (it can be repeated) 529 | angleDeg: rotation angle in degrees counter-clockwise (default 0) 530 | """ 531 | 532 | group = self.createGroup(parent, label) 533 | elem = self.createGroup(group, label) 534 | 535 | inkDraw.line.relCoords(elem, [[0, 10]], position) 536 | inkDraw.line.relCoords(elem, [[-14, 0]], [position[0] + 7, position[1] + 10]) 537 | inkDraw.line.relCoords(elem, [[-7, 0]], [position[0] + 3.5, position[1] + 12]) 538 | inkDraw.line.relCoords(elem, [[-2, 0]], [position[0] + 1, position[1] + 14]) 539 | 540 | if angleDeg != 0: 541 | self.rotateElement(group, position, angleDeg) 542 | 543 | return group 544 | 545 | # --------------------------------------------- 546 | def drawCommon(self, parent, position=[0, 0], label='Common', angleDeg=0): 547 | """ draws a GND 548 | 549 | parent: parent object 550 | position: position [x,y] 551 | label: label of the object (it can be repeated) 552 | angleDeg: rotation angle in degrees counter-clockwise (default 0) 553 | """ 554 | 555 | group = self.createGroup(parent, label) 556 | elem = self.createGroup(group, label) 557 | 558 | inkDraw.line.relCoords(elem, [[0, 10]], position) 559 | inkDraw.line.relCoords(elem, [[-10, 0], [5, 5], [5, -5]], [position[0] + 5, position[1] + 10]) 560 | 561 | if angleDeg != 0: 562 | self.rotateElement(group, position, angleDeg) 563 | 564 | return group 565 | 566 | # --------------------------------------------- 567 | def createLatch(self, parent, position=[0, 0], label='Latch', type='SRnor', controlGate='none', controlGateLogic=True, asynPreset=0, asynClear=0, 568 | size='large', suppressq=False, suppressNOTq=False): 569 | """ draws latches 570 | 571 | parent: parent object 572 | position: position [x,y] 573 | label: label of the object (it can be repeated) 574 | type: type of latch/Flip-flop. Available values: 'SRnor','SRnand','D','JK','T' 575 | controlGate: type of the gate input: available values: 'none','level', 'edge' 576 | controlGateLogic: True: activate HIGH (or rising edge) False: activate LOW (or falling edge) 577 | asynPreset: Asyncrhonous preset 578 | asynClear: Asyncrhonous clear 579 | 1: active HIGH 580 | 0: no input 581 | -1: active LOW 582 | reducedSize: predefined size. Available values: 'large', 'medium', 'small' 583 | suppressq: suppress drawing he direct state output. Default: False 584 | suppressNOTq: suppress drawing he inverted state output. Default: False 585 | """ 586 | group = self.createGroup(parent, label) 587 | 588 | if type == 'SRnor' or type == 'SRnand' or type == 'JK': 589 | if size == 'large': 590 | w = 50 591 | h = 70 592 | dist_signal = 20 593 | y_controlGate = 0 594 | if size == 'medium': 595 | w = 40 596 | h = 50 597 | dist_signal = 15 598 | y_controlGate = 0 599 | if size == 'small': 600 | w = 30 601 | h = 40 602 | dist_signal = 10 603 | y_controlGate = 0 604 | 605 | if type == 'D' or type == 'T': 606 | if size == 'large': 607 | w = 50 608 | h = 60 609 | dist_signal = 15 610 | y_controlGate = 15 611 | if size == 'medium': 612 | w = 40 613 | h = 40 614 | dist_signal = 10 615 | y_controlGate = 10 616 | if size == 'small': 617 | w = 30 618 | h = 35 619 | dist_signal = 7.5 620 | y_controlGate = 7.5 621 | 622 | if size == 'large': 623 | fontSizeFactorG = 1.2 624 | fontSizeFactorS = 0.8 625 | if size == 'medium': 626 | fontSizeFactorG = 1.0 627 | fontSizeFactorS = 0.6 628 | if size == 'small': 629 | fontSizeFactorG = 1.0 630 | fontSizeFactorS = 0.5 631 | 632 | x_min = position[0] - w / 2.0 633 | x_max = position[0] + w / 2.0 634 | y_min = position[1] + h / 2.0 635 | y_max = position[1] - h / 2.0 636 | 637 | inkDraw.rectangle.widthHeightCenter(group, centerPoint=position, width=w, height=h, lineStyle=inkDraw.lineStyle.setSimpleBlack(1.5)) 638 | 639 | if not suppressq: 640 | if not inkDraw.useLatex: 641 | self.createOutput(True, group, position=[x_max, position[1] - dist_signal], extraLength=0.0, label='Q', name='Q', 642 | fontSizeFactor=fontSizeFactorG) 643 | else: 644 | self.createOutput(True, group, position=[x_max, position[1] - dist_signal], extraLength=0.0, label='Q', name='$Q$', 645 | fontSizeFactor=fontSizeFactorG) 646 | 647 | if not suppressNOTq: 648 | if not inkDraw.useLatex: 649 | self.createOutput(True, group, position=[x_max, position[1] + dist_signal], extraLength=0.0, label='notQ', name=u'\u00ACQ', 650 | fontSizeFactor=fontSizeFactorG) 651 | else: 652 | self.createOutput(True, group, position=[x_max, position[1] + dist_signal], extraLength=0.0, label='notQ', name=r'$\NOT{Q}$', 653 | fontSizeFactor=fontSizeFactorG) 654 | 655 | # Asyncronous Preset and Clear 656 | if asynPreset == 1: 657 | self.createSignal(True, group, position=[position[0], y_max], direction='N', name='PRE', fontSizeFactor=fontSizeFactorS) 658 | elif asynPreset == -1: 659 | self.createSignal(False, group, position=[position[0], y_max], direction='N', name='PRE', fontSizeFactor=fontSizeFactorS) 660 | 661 | if asynClear == 1: 662 | self.createSignal(True, group, position=[position[0], y_min], direction='S', name='CLR', fontSizeFactor=fontSizeFactorS) 663 | elif asynClear == -1: 664 | self.createSignal(False, group, position=[position[0], y_min], direction='S', name='CLR', fontSizeFactor=fontSizeFactorS) 665 | 666 | if controlGate == 'level': 667 | self.createSignal(controlGateLogic, group, position=[x_min, position[1] + y_controlGate], direction='W', name='EN', isClock=False, 668 | fontSizeFactor=fontSizeFactorS) 669 | if controlGate == 'edge': 670 | self.createSignal(controlGateLogic, group, position=[x_min, position[1] + y_controlGate], direction='W', name='CLK', isClock=True, 671 | fontSizeFactor=fontSizeFactorS) 672 | 673 | if type == 'SRnor' or type == 'JK': 674 | if not inkDraw.useLatex: 675 | self.createInput(True, group, position=[x_min, position[1] - dist_signal], extraLength=0.0, name=type[0], 676 | fontSizeFactor=fontSizeFactorG) 677 | self.createInput(True, group, position=[x_min, position[1] + dist_signal], extraLength=0.0, name=type[1], 678 | fontSizeFactor=fontSizeFactorG) 679 | else: 680 | self.createInput(True, group, position=[x_min, position[1] - dist_signal], extraLength=0.0, name='$' + type[0] + '$', 681 | fontSizeFactor=fontSizeFactorG) 682 | self.createInput(True, group, position=[x_min, position[1] + dist_signal], extraLength=0.0, name='$' + type[1] + '$', 683 | fontSizeFactor=fontSizeFactorG) 684 | 685 | elif type == 'SRnand': 686 | if not inkDraw.useLatex: 687 | input1 = u'\u00AC%s' % type[0] 688 | input2 = u'\u00AC%s' % type[1] 689 | else: 690 | input1 = r'\NOT{%s}' % type[0] 691 | input2 = r'\NOT{%s}' % type[1] 692 | self.createInput(True, group, position=[x_min, position[1] - dist_signal], extraLength=0.0, name=input1, fontSizeFactor=fontSizeFactorG) 693 | self.createInput(True, group, position=[x_min, position[1] + dist_signal], extraLength=0.0, name=input2, fontSizeFactor=fontSizeFactorG) 694 | elif type == 'D' or type == 'T': 695 | if not inkDraw.useLatex: 696 | self.createInput(True, group, position=[x_min, position[1] - dist_signal], extraLength=0.0, name=type, fontSizeFactor=fontSizeFactorG) 697 | else: 698 | self.createInput(True, group, position=[x_min, position[1] - dist_signal], extraLength=0.0, name='$' + type + '$', 699 | fontSizeFactor=fontSizeFactorG) 700 | 701 | 702 | if __name__ == '__main__': 703 | logic = LogicGates() 704 | logic.affect() 705 | --------------------------------------------------------------------------------