diff --git a/src/cheatsheets/Digitaltechnik.typ b/src/cheatsheets/Digitaltechnik.typ index 872889e..eda9835 100644 --- a/src/cheatsheets/Digitaltechnik.typ +++ b/src/cheatsheets/Digitaltechnik.typ @@ -2,6 +2,7 @@ #import "@preview/mannot:0.3.1" #import "@preview/cetz:0.4.2" #import "@preview/zap:0.5.0" +#import "../lib/truthtable.typ" : * #show math.integral: it => math.limits(math.integral) #show math.sum: it => math.limits(math.sum) @@ -21,6 +22,7 @@ columns: (1fr, 1fr, 1fr), [#align(left, datetime.today().display("[day].[month].[year]"))], [#align(center, counter(page).display("- 1 -"))], + [Thanks to Daniel for the circuit Symbols], [#align(right, image("../images/cc0.png", height: 5mm,))] ) ], @@ -205,6 +207,7 @@ ] ) + #zap.circuit({ import cetz.draw : * import zap : * @@ -228,56 +231,88 @@ content((1.75, 0.5), "+") }) - #zap.circuit({ - import cetz.draw : * - import zap : * - rect((1.5,0),(4-1.5, 0.1), fill: rgb("#535353"), stroke: none) - rect((0,0),(4,-1), fill: pTypeFill, stroke: none) - rect((0.5,-0),(1.5, -0.5), fill: nTypeFill, stroke: none) - rect((4 - 1.5,-0),(4-0.5, -0.5), fill: nTypeFill, stroke: none) -rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", thickness: 0.06)) -< - line((3, 0.3), (3, 0)) - line((1, 0.3), (1, 0)) - line((2, 0.3), (2, 0.1)) + #grid( + columns: (1fr, 1fr), + column-gutter: 6mm, + align: center, + [#align(center)[*PMOS*]], [#align(center)[*CMOS*]], + grid.cell(inset: 2mm, + align(center, + zap.circuit({ + import "../lib/circuit.typ" : * - cetz.decorations.brace((2.5,-0.5),(1.5,-0.5)) - content((2, -1.3), "Channel") - content((3, -0.25), "N") - content((1, -0.25), "N") - content((0.5, -0.75), "P") + registerAllCustom(); + fet("T", (0,0), type: "P", scale: 150%); + }) + ) + ), + grid.cell(inset: 2mm, + align(center, + zap.circuit({ + import "../lib/circuit.typ" : * - content((3, 0.5), "S") - content((1, 0.5), "D") - content((2, 0.5), "G") - }) + registerAllCustom(); + fet("T", (0,0), type: "N", scale: 150%); + }), + ) + ), + scale( + x: 75%, y: 75%, + zap.circuit({ + import cetz.draw : * + import zap : * + rect((1.5,0),(4-1.5, 0.1), fill: rgb("#535353"), stroke: none) + rect((0,0),(4,-1), fill: pTypeFill, stroke: none) + rect((0.5,-0),(1.5, -0.5), fill: nTypeFill, stroke: none) + rect((4 - 1.5,-0),(4-0.5, -0.5), fill: nTypeFill, stroke: none) + rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", thickness: 0.06)) - #zap.circuit({ - import cetz.draw : * - import zap : * - rect((1.5,0),(4-1.5, 0.1), fill: rgb("#535353"), stroke: none) - rect((0,0),(4,-1), fill: nTypeFill, stroke: none) - rect((0.5,-0),(1.5, -0.5), fill: pTypeFill, stroke: none) - rect((4 - 1.5,-0),(4-0.5, -0.5), fill: pTypeFill, stroke: none) - rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", thickness: 0.06)) + line((3, 0.3), (3, 0)) + line((1, 0.3), (1, 0)) + line((2, 0.3), (2, 0.1)) - line((3, 0.3), (3, 0)) - line((1, 0.3), (1, 0)) - line((2, 0.3), (2, 0.1)) + cetz.decorations.brace((2.5,-0.6),(1.5,-0.6)) + content((2, -1.3), "Channel") + content((3, -0.25), "N") + content((1, -0.25), "N") + content((0.5, -0.75), "P") - cetz.decorations.brace((2.5,-0.5),(1.5,-0.5)) - content((2, -1.3), "Channel") - content((3, -0.25), "P") - content((1, -0.25), "P") - content((0.5, -0.75), "N") + content((3, 0.5), "S") + content((1, 0.5), "D") + content((2, 0.5), "G") + }) + ), + scale( + x: 75%, y: 75%, + zap.circuit({ + import cetz.draw : * + import zap : * + rect((1.5,0),(4-1.5, 0.1), fill: rgb("#535353"), stroke: none) + rect((0,0),(4,-1), fill: nTypeFill, stroke: none) + rect((0.5,-0),(1.5, -0.5), fill: pTypeFill, stroke: none) + rect((4 - 1.5,-0),(4-0.5, -0.5), fill: pTypeFill, stroke: none) + rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", thickness: 0.06)) - content((3, 0.5), "S") - content((1, 0.5), "D") - content((2, 0.5), "G") - }) + line((3, 0.3), (3, 0)) + line((1, 0.3), (1, 0)) + line((2, 0.3), (2, 0.1)) + + cetz.decorations.brace((2.5,-0.6),(1.5,-0.6)) + content((2, -1.3), "Channel") + content((3, -0.25), "P") + content((1, -0.25), "P") + content((0.5, -0.75), "N") + + content((3, 0.5), "S") + content((1, 0.5), "D") + content((2, 0.5), "G") + }) + ), + + + ) ] - // Quine McCluskey #bgBlock(fill: colorOptimierung)[ #subHeading(fill: colorOptimierung)[Quine McCluskey] @@ -285,7 +320,131 @@ rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", th // NMOS/PMOS #bgBlock(fill: colorRealsierung)[ - #subHeading(fill: colorRealsierung)[NMOS/PMOS] + #subHeading(fill: colorRealsierung)[CMOS] + $hat(=)$ Complemntary MOS + + #table( + columns: (1fr, 1fr), + zap.circuit({ + import zap : * + import cetz.draw : content + import "../lib/circuit.typ" : * + + set-style(wire: (stroke: (thickness: 0.025))) + + registerAllCustom(); + fet("N0", (0,0), type: "N", angle: 90deg); + fet("P0", (0,1), type: "P", angle: 90deg); + wire("N0.G", (rel: (-0.1, 0)), (horizontal: (), vertical: "P0.G"), "P0.G") + + node("outNode", (0,0.5)) + node("inNode", (-0.6,0.5)) + wire((-1, 0.5), "inNode") + wire((0.2, 0.5), "outNode") + + node("N2", (0,-0.5)) + node("N2", (0,1.5)) + + wire((-1, -0.5), (0.5, -0.5)) + wire((-1, 1.5), (0.5, 1.5)) + + content((-1, 0.5), scale($"X"$, 60%), anchor: "east") + content((0.45, 0.5), scale($overline("X")$, 60%), anchor: "east") + content((-0.9, 1.5), scale($"U"_"DD"$, 60%), anchor: "east") + content((-0.9, -0.5), scale($"GND"$, 60%), anchor: "east") + }), + + [ + *Inverter* + + $overline(X)$ + ], + + zap.circuit({ + import zap : * + import cetz.draw : content + import "../lib/circuit.typ" : * + + set-style(wire: (stroke: (thickness: 0.025))) + + registerAllCustom(); + fet("P0", (0.5,0.25), type: "P", angle: 90deg); + fet("P1", (0.5,1.25), type: "P", angle: 90deg); + fet("N0", (0,-1), type: "N", angle: 90deg); + fet("N1", (1,-1), type: "N", angle: 90deg); + + content((-0.7, 1.75), scale($"V"_"DD"$, 60%), anchor: "east") + content((-0.7, -1.5), scale($"GND"$, 60%), anchor: "east") + + content("N0.G", scale($"B"$, 60%), anchor: "east") + content("P0.G", scale($"B"$, 60%), anchor: "east") + content("N1.G", scale($"A"$, 60%), anchor: "east") + content("P1.G", scale($"A"$, 60%), anchor: "east") + + wire((-0.75, -1.5), (1.5, -1.5)) + wire((-0.75, 1.75), (1.5, 1.75)) + + wire("N0.S", "N1.S") + node("N2", "P0.D") + wire("N2", (horizontal: (), vertical: "N0.S")) + node("N3", "N0.D") + node("N4", "N1.D") + node("N5", "P1.S") + node("N6", (horizontal: (), vertical: "N0.S")) + + wire("N2", (horizontal: (rel: (0.5, 0)), vertical: "N2")) + + content((horizontal: (rel: (0.65, 0)), vertical: "N2"), scale($"Y"$, 60%)) + }), + + [ + *NOR* + + $overline(A +B) = Y$ + ], + + zap.circuit({ + import zap : * + import cetz.draw : content + import "../lib/circuit.typ" : * + + set-style(wire: (stroke: (thickness: 0.025))) + + registerAllCustom(); + content((-0.7, 0.5), scale($"V"_"DD"$, 60%), anchor: "east") + content((-0.7, -2.75), scale($"GND"$, 60%), anchor: "east") + + fet("P0", (0, 0), type: "P", angle: 90deg); + fet("P1", (1, 0), type: "P", angle: 90deg); + fet("N0", (0.5,-1.25), type: "N", angle: 90deg); + fet("N1", (0.5,-2.25), type: "N", angle: 90deg); + + wire((-0.75, 0.5), (1.5, 0.5)) + wire((-0.75, -2.75), (1.5, -2.75)) + wire("P0.D", "P1.D") + + node("N2", (horizontal: "N1.D", vertical: "P0.D")) + node("N3", "N0.S") + wire("N2", "N3") + wire("N3", (rel: (0.5, 0))) + + content((horizontal: (rel: (0.65, 0)), vertical: "N3"), scale($"Z"$, 60%)) + node("4", "P0.S") + node("4", "P1.S") + node("4", "N1.D") + + content("N0.G", scale($"B"$, 60%), anchor: "east") + content("P0.G", scale($"B"$, 60%), anchor: "east") + content("N1.G", scale($"A"$, 60%), anchor: "east") + content("P1.G", scale($"A"$, 60%), anchor: "east") + }), + + [ + *NAND* + + $overline(A dot B) = Y$ + ], + ) ] // CMOS @@ -427,9 +586,6 @@ rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", th - Leckstom (weil Diode) - Gatestrom - - - *Schaltrate* $alpha_"clk" = 100%$ @@ -437,4 +593,19 @@ rect((1.5,-0),(2.5, -0.5), fill: none, stroke: (paint: black, dash: "dotted", th $alpha_"logic" = 50%$ ] -] \ No newline at end of file +] + +#place(bottom, + truth-table( + outputs: ( + ("NAND", (1, 1, 1, 0)), + ("NOR", (1, 0, 0, 0)), + ("XNOR", (1, 0, 0, 1)), + ("XOR", (0, 1, 1, 0)), + ("AND", (0, 0, 0, 1)), + ("OR", (0, 1, 1, 1)), + ), + inputs: ("A", "B") + ), + float: true +) \ No newline at end of file diff --git a/src/lib/circuit.typ b/src/lib/circuit.typ index 1e91d9d..f09b286 100644 --- a/src/lib/circuit.typ +++ b/src/lib/circuit.typ @@ -3,16 +3,6 @@ #import zap: interface #let registerAllCustom() = { - cetz.draw.set-ctx(ctx => { - ctx.zap.style.insert("einTor", ( - scale: auto, - fill: auto, - height: 3mm, - width: 6mm, - )) - ctx - }) - cetz.draw.set-ctx(ctx => { ctx.zap.style.insert("zweiTor", ( scale: auto, @@ -20,8 +10,39 @@ height: 10mm, width: 10mm, )) + + ctx.zap.style.insert("einTor", ( + scale: auto, + fill: auto, + height: 3mm, + width: 6mm, + )) + + ctx.zap.style.insert("fet", ( + scale: auto, + fill: none, + height: 5mm, + width: 10mm, + )) + + + for it in ("lnot", "land", "lnand", "lor", "lnor", "lxor", "lxnor") { + ctx.zap.style.insert(it, ( + width: 0.7, + min-height: 0.9, + spacing: 0.4, + padding: 0.25, + fill: white, + stroke: auto, + ) + ) + } + ctx }) + + + } #let einTor(name, node, flip: false, ..params) = { @@ -83,4 +104,53 @@ // Component call component("zweiTor", name, node, draw: draw, ..params) +} + +#let fet(name, node, type: "N", scale: 1, angle: 0, thickness: 0.5pt, ..params) = { + import cetz.draw: line, circle, anchor, rotate + import zap: component + + // Drawing function + let draw(ctx, position, style) = { + let zap-style = ctx.zap.style + + let height = style.height * scale; + let width = style.width * scale; + + let wireThink = ctx.zap.style.wire.stroke.thickness; + + rotate(angle); + + if(type == "N") { + line((0, height), (0, height*(1-0.45)), stroke: (thickness: wireThink)) + } else { + line((0, height), (0, height*(1-0.2)), stroke: (thickness: wireThink)) + circle((0, height*(1-0.3) - thickness/2), radius: (height/2)*0.2, stroke: (thickness: wireThink)) + } + + line( + (width/2, 0), + (width*0.4/2, 0), + (width*0.4/2, 0), + (width*0.4/2, height*(1-0.6)), + (-width*0.4/2, height*(1-0.6)), + (-width*0.4/2, 0), + (-width/2, 0), stroke: (thickness: wireThink) + ) + + line( + (width*0.42/2, height*(1-0.45)), + (-width*0.42/2, height*(1-0.45)), + stroke: (thickness: wireThink) + ) + + anchor("G", (0, height)) + anchor("D", (-width/2, 0)) + anchor("S", (width/2, 0)) + + interface((-width / 2, -height / 2), (width / 2, height / 2), io: true) + } + + // Component call + component("fet", name, node, draw: draw, ..params) } \ No newline at end of file diff --git a/src/lib/logic.typ b/src/lib/logic.typ new file mode 100644 index 0000000..a760452 --- /dev/null +++ b/src/lib/logic.typ @@ -0,0 +1,62 @@ +#import "@preview/zap:0.5.0": * +#import "@preview/cetz:0.4.2": ( + draw.anchor, draw.arc-through, draw.circle, draw.content, draw.line, draw.rect, draw.rotate, draw.get-ctx, draw.bezier +) + +#let logic(name, node, text: $"&"$, invert: false, mirror: false, invert-inputs: (), angle: 0deg, inputs: 2, ..params) = { + assert(inputs >= 1, message: "logic supports minimum one inputs") + + let style = ( + width: 0.7, + min-height: 0.9, + spacing: 0.4, + padding: 0.25, + fill: white, + stroke: auto, + ) + + // Drawing function + let draw(ctx, position, _) = { + rotate(angle) + + let height = calc.max(style.min-height, (inputs - 1) * style.spacing + 2 * style.padding) + let width = style.width * if mirror { -1 } else { 1 } + + interface((-width / 2, -height / 2), (width / 2, height / 2), io: false) + + rect((-width / 2, -height / 2), (rel: (width, height)), fill: style.fill, stroke: style.stroke) + content((0, height / 2 - style.padding / 2), text, anchor: "north", angle: angle) + + let ball-radius = calc.min(height, width) * 0.1 + + for input in range(1, inputs + 1) { + let pad = (height - (inputs - 1) * style.spacing) / 2 + let y = height / 2 - pad - (input - 1) * style.spacing; + + if input in invert-inputs { + circle((-width / 2 - ball-radius, y), radius: ball-radius, stroke: style.stroke, fill: style.fill) + anchor("in" + str(input), (-width / 2, y)) + } else { + anchor("in" + str(input), (-width / 2, y)) + } + } + + if invert { + circle((width / 2 + ball-radius, 0), radius: ball-radius, stroke: style.stroke, fill: style.fill) + anchor("out", (width / 2, 0)) + } else { + anchor("out", (width / 2, 0)) + } + } + + // Component call + component("logic", name, node, draw: draw, ..params) +} + +#let lnot(name, node, ..params) = logic(name, node, ..params, text: $1$, invert: true) +#let land(name, node, ..params) = logic(name, node, ..params, text: $"&"$) +#let lnand(name, node, ..params) = logic(name, node, ..params, text: $"&"$, invert: true) +#let lor(name, node, ..params) = logic(name, node, ..params, text: $>=1$) +#let lnor(name, node, ..params) = logic(name, node, ..params, text: $>=1$, invert: true) +#let lxor(name, node, ..params) = logic(name, node, ..params, text: $=1$) +#let lxnor(name, node, ..params) = logic(name, node, ..params, text: $=1$, invert: true) \ No newline at end of file diff --git a/src/lib/table.typ b/src/lib/table.typ new file mode 100644 index 0000000..76de629 --- /dev/null +++ b/src/lib/table.typ @@ -0,0 +1,80 @@ +#import "@preview/zap:0.5.0" +#import "logic.typ" + +#let circuit(body) = zap.circuit({ + import zap: * + + set-style( + node: ( + radius: 0.04, + ) + ) + + body +}) + +#table( + columns: (1fr, 1fr), + align: center + horizon, + stroke: (x, y) => ( + left: if x > 0 { 0.5pt }, + top: if y == 1 { 1pt } else if y > 0 { 0.5pt }, + ), + table.header([DNF], [KNF]), + circuit({ + import zap: * + + logic.land("A1", (0, 0.75), invert-inputs: (1,)) + logic.land("A2", (0, -0.75), invert-inputs: (2,)) + + logic.lor("O1", (1.25, 0)) + + zwire("A1.out", "O1.in1", ratio: 50%) + zwire("A2.out", "O1.in2", ratio: 50%) + + wire((-1, 1.25), (-1, -1.25), name: "A") + wire((-0.75, 1.25), (-0.75, -1.25), name: "B") + + cetz.draw.content("A.in", [a], anchor: "south", padding: 2pt) + cetz.draw.content("B.in", [b], anchor: "south", padding: 2pt) + + node("N4", ("A1.in1", "-|", "A.in")) + wire("A1.in1", "N4") + node("N3", ("A1.in2", "-|", "B.in")) + wire("A1.in2", "N3") + node("N2", ("A2.in1", "-|", "A.in")) + wire("A2.in1", "N2") + node("N1", ("A2.in2", "-|", "B.in")) + wire("A2.in2", "N1") + + wire("O1.out", (rel: (0.3, 0))) + }), + circuit({ + import zap: * + + logic.lor("A1", (0, 0.75)) + logic.lor("A2", (0, -0.75), invert-inputs: (1,2)) + + logic.land("O1", (1.25, 0)) + + zwire("A1.out", "O1.in1", ratio: 50%) + zwire("A2.out", "O1.in2", ratio: 50%) + + wire((-1, 1.25), (-1, -1.25), name: "A") + wire((-0.75, 1.25), (-0.75, -1.25), name: "B") + + cetz.draw.content("A.in", [a], anchor: "south", padding: 2pt) + cetz.draw.content("B.in", [b], anchor: "south", padding: 2pt) + + node("N4", ("A1.in1", "-|", "A.in")) + wire("A1.in1", "N4") + node("N3", ("A1.in2", "-|", "B.in")) + wire("A1.in2", "N3") + node("N2", ("A2.in1", "-|", "A.in")) + wire("A2.in1", "N2") + node("N1", ("A2.in2", "-|", "B.in")) + wire("A2.in2", "N1") + + wire("O1.out", (rel: (0.3, 0))) + }) +) \ No newline at end of file diff --git a/src/lib/truthtable.typ b/src/lib/truthtable.typ new file mode 100644 index 0000000..ae4e9b7 --- /dev/null +++ b/src/lib/truthtable.typ @@ -0,0 +1,35 @@ +#let truth-table(outputs: (), inputs: none) = { + let variables = calc.max(..outputs.map(output => calc.ceil(calc.log(output.at(1).len()) / calc.log(2)))) + + if inputs == none { + inputs = ($a$, $b$, $c$, $d$).slice(0, variables) + } + + assert(outputs.len() >= 1, message: "There has to be at least one output") + assert(inputs.len() == variables, message: "There aren't enough variables to label") + + let num-to-bin(x, digits) = { + let bits = () + + while x != 0 { + bits.push(calc.rem(x, 2)) + + x = calc.floor(x / 2) + } + + range(digits).map(x => bits.at(digits - x - 1, default: 0)) + } + + table( + columns: (auto,) * (variables + outputs.len()), + stroke: (x, y) => ( + left: if x == variables { 1pt } else if x > 0 { 0.5pt }, + top: if y == 1 { 1pt } else if y > 0 { 0.5pt }, + ), + inset: 4pt, + if inputs != none { table.header(..inputs.map(x => [#x]), ..outputs.map(((x, _)) => [#x])) }, + ..range(calc.pow(2, variables)) + .map(x => (..num-to-bin(x, variables).map(y => [#y]), ..outputs.map(((_, y)) => [#y.at(x, default: [])]))) + .flatten() + ) +} \ No newline at end of file