// Pre-built example circuits // Each example is a { gates, connections, nextId, camera } object const W = 100; // GATE_W const H = 60; // GATE_H const GAP_X = 160; const GAP_Y = 100; /** * SR Flip-Flop using cross-coupled NOR gates * * S ──┐ * NOR─── Q * ┌──┘ │ * │ │ * └──┐ │ * NOR─── Q̅ * R ──┘ */ function srFlipFlop() { const gates = [ // Inputs { id: 1, type: 'INPUT', x: 50, y: 80, value: 0, label: 'S' }, { id: 2, type: 'INPUT', x: 50, y: 280, value: 0, label: 'R' }, // Cross-coupled NOR gates { id: 3, type: 'NOR', x: 300, y: 80, value: 0 }, { id: 4, type: 'NOR', x: 300, y: 280, value: 0 }, // Outputs { id: 5, type: 'OUTPUT', x: 550, y: 80, value: 0, label: 'Q' }, { id: 6, type: 'OUTPUT', x: 550, y: 280, value: 0, label: 'Q̅' } ]; const connections = [ // S → Top NOR input 0 { from: 1, fromPort: 0, to: 3, toPort: 0 }, // R → Bottom NOR input 1 { from: 2, fromPort: 0, to: 4, toPort: 1 }, // Top NOR (Q) → Bottom NOR input 0 (cross-couple) { from: 3, fromPort: 0, to: 4, toPort: 0 }, // Bottom NOR (Q̅) → Top NOR input 1 (cross-couple) { from: 4, fromPort: 0, to: 3, toPort: 1 }, // NOR outputs → visible outputs { from: 3, fromPort: 0, to: 5, toPort: 0 }, { from: 4, fromPort: 0, to: 6, toPort: 0 } ]; return { name: 'SR Flip-Flop (NOR)', description: 'Set-Reset latch using cross-coupled NOR gates. Toggle S to set Q=1, toggle R to reset Q=0.', gates, connections, nextId: 7, camera: { camX: 0, camY: 0, zoom: 1 } }; } /** * SR Flip-Flop using cross-coupled NAND gates * * S̅ ──┐ * NAND── Q * ┌───┘ │ * │ │ * └───┐ │ * NAND── Q̅ * R̅ ──┘ */ function srFlipFlopNand() { const gates = [ // Inputs (active low for NAND SR) { id: 1, type: 'INPUT', x: 50, y: 80, value: 1, label: 'S̅' }, { id: 2, type: 'INPUT', x: 50, y: 280, value: 1, label: 'R̅' }, // Cross-coupled NAND gates { id: 3, type: 'NAND', x: 300, y: 80, value: 0 }, { id: 4, type: 'NAND', x: 300, y: 280, value: 0 }, // Outputs { id: 5, type: 'OUTPUT', x: 550, y: 80, value: 0, label: 'Q' }, { id: 6, type: 'OUTPUT', x: 550, y: 280, value: 0, label: 'Q̅' } ]; const connections = [ // S̅ → Top NAND input 0 { from: 1, fromPort: 0, to: 3, toPort: 0 }, // R̅ → Bottom NAND input 1 { from: 2, fromPort: 0, to: 4, toPort: 1 }, // Top NAND (Q) → Bottom NAND input 0 (cross-couple) { from: 3, fromPort: 0, to: 4, toPort: 0 }, // Bottom NAND (Q̅) → Top NAND input 1 (cross-couple) { from: 4, fromPort: 0, to: 3, toPort: 1 }, // Outputs { from: 3, fromPort: 0, to: 5, toPort: 0 }, { from: 4, fromPort: 0, to: 6, toPort: 0 } ]; return { name: 'SR Flip-Flop (NAND)', description: 'Set-Reset latch using cross-coupled NAND gates. Inputs are active-low: set S̅=0 to set, R̅=0 to reset.', gates, connections, nextId: 7, camera: { camX: 0, camY: 0, zoom: 1 } }; } /** * Gated D Latch (1-bit memory) * * Uses an SR flip-flop with gating logic: * D ──AND──┐ * E ──┤ NOR── Q * │ │ ┌──┘│ * │ │ │ │ * │ │ └──┐│ * E ──┤ NOR── Q̅ * D─NOT─AND┘ * * When Enable=1, Q follows D. * When Enable=0, Q holds its value. */ function dLatch() { const gates = [ // Inputs { id: 1, type: 'INPUT', x: 50, y: 100, value: 0, label: 'D' }, { id: 2, type: 'INPUT', x: 50, y: 280, value: 0, label: 'EN' }, // NOT gate to invert D { id: 3, type: 'NOT', x: 200, y: 340, value: 0 }, // AND gates for gating { id: 4, type: 'AND', x: 350, y: 60, value: 0 }, // D AND E → S { id: 5, type: 'AND', x: 350, y: 340, value: 0 }, // NOT(D) AND E → R // Cross-coupled NOR gates (SR latch core) { id: 6, type: 'NOR', x: 550, y: 60, value: 0 }, // → Q { id: 7, type: 'NOR', x: 550, y: 340, value: 0 }, // → Q̅ // Outputs { id: 8, type: 'OUTPUT', x: 750, y: 60, value: 0, label: 'Q' }, { id: 9, type: 'OUTPUT', x: 750, y: 340, value: 0, label: 'Q̅' } ]; const connections = [ // D → AND top input, and D → NOT { from: 1, fromPort: 0, to: 4, toPort: 0 }, { from: 1, fromPort: 0, to: 3, toPort: 0 }, // E → both AND gates { from: 2, fromPort: 0, to: 4, toPort: 1 }, { from: 2, fromPort: 0, to: 5, toPort: 1 }, // NOT(D) → bottom AND { from: 3, fromPort: 0, to: 5, toPort: 0 }, // AND outputs → NOR inputs (S and R) { from: 4, fromPort: 0, to: 6, toPort: 0 }, { from: 5, fromPort: 0, to: 7, toPort: 1 }, // Cross-coupling { from: 6, fromPort: 0, to: 7, toPort: 0 }, { from: 7, fromPort: 0, to: 6, toPort: 1 }, // Outputs { from: 6, fromPort: 0, to: 8, toPort: 0 }, { from: 7, fromPort: 0, to: 9, toPort: 0 } ]; return { name: 'D Latch (1-bit Memory)', description: 'Gated D latch — a 1-bit memory cell. When Enable=1, output Q follows input D. When Enable=0, Q holds its last value.', gates, connections, nextId: 10, camera: { camX: 0, camY: 0, zoom: 1 } }; } /** * D Flip-Flop (edge-triggered, master-slave) * * Two D latches in series with inverted enable: * - Master latch captures D when CLK=0 * - Slave latch outputs when CLK=1 * This creates rising-edge triggered behavior. */ function dFlipFlop() { const gates = [ // Inputs { id: 1, type: 'INPUT', x: 30, y: 100, value: 0, label: 'D' }, { id: 2, type: 'CLOCK', x: 30, y: 350, value: 0, label: 'CLK' }, // CLK inverter (for master latch) { id: 3, type: 'NOT', x: 170, y: 350, value: 0 }, // === MASTER LATCH (enabled when CLK=0, i.e. NOT CLK=1) === { id: 4, type: 'NOT', x: 170, y: 200, value: 0 }, // NOT D for master { id: 5, type: 'AND', x: 300, y: 60, value: 0 }, // D AND !CLK { id: 6, type: 'AND', x: 300, y: 240, value: 0 }, // !D AND !CLK { id: 7, type: 'NOR', x: 450, y: 60, value: 0 }, // Master Q { id: 8, type: 'NOR', x: 450, y: 240, value: 0 }, // Master Q̅ // === SLAVE LATCH (enabled when CLK=1) === { id: 9, type: 'NOT', x: 570, y: 200, value: 0 }, // NOT master Q for slave { id: 10, type: 'AND', x: 680, y: 60, value: 0 }, // masterQ AND CLK { id: 11, type: 'AND', x: 680, y: 240, value: 0 }, // !masterQ AND CLK { id: 12, type: 'NOR', x: 830, y: 60, value: 0 }, // Slave Q { id: 13, type: 'NOR', x: 830, y: 240, value: 0 }, // Slave Q̅ // Outputs { id: 14, type: 'OUTPUT', x: 1010, y: 60, value: 0, label: 'Q' }, { id: 15, type: 'OUTPUT', x: 1010, y: 240, value: 0, label: 'Q̅' } ]; const connections = [ // D → master AND, D → master NOT { from: 1, fromPort: 0, to: 5, toPort: 0 }, { from: 1, fromPort: 0, to: 4, toPort: 0 }, // CLK → NOT (invert for master) { from: 2, fromPort: 0, to: 3, toPort: 0 }, // !CLK → master AND gates (enable) { from: 3, fromPort: 0, to: 5, toPort: 1 }, { from: 3, fromPort: 0, to: 6, toPort: 1 }, // !D → master bottom AND { from: 4, fromPort: 0, to: 6, toPort: 0 }, // Master AND outputs → Master NOR (SR latch) { from: 5, fromPort: 0, to: 7, toPort: 0 }, { from: 6, fromPort: 0, to: 8, toPort: 1 }, // Master cross-coupling { from: 7, fromPort: 0, to: 8, toPort: 0 }, { from: 8, fromPort: 0, to: 7, toPort: 1 }, // Master Q → slave AND, Master Q → slave NOT { from: 7, fromPort: 0, to: 10, toPort: 0 }, { from: 7, fromPort: 0, to: 9, toPort: 0 }, // CLK → slave AND gates (enable, direct CLK) { from: 2, fromPort: 0, to: 10, toPort: 1 }, { from: 2, fromPort: 0, to: 11, toPort: 1 }, // !masterQ → slave bottom AND { from: 9, fromPort: 0, to: 11, toPort: 0 }, // Slave AND outputs → Slave NOR (SR latch) { from: 10, fromPort: 0, to: 12, toPort: 0 }, { from: 11, fromPort: 0, to: 13, toPort: 1 }, // Slave cross-coupling { from: 12, fromPort: 0, to: 13, toPort: 0 }, { from: 13, fromPort: 0, to: 12, toPort: 1 }, // Outputs { from: 12, fromPort: 0, to: 14, toPort: 0 }, { from: 13, fromPort: 0, to: 15, toPort: 0 } ]; return { name: 'D Flip-Flop (Master-Slave)', description: 'Edge-triggered D flip-flop built from two D latches. Captures D on the rising edge of CLK. Use with the clock simulation to see it in action.', gates, connections, nextId: 16, camera: { camX: 0, camY: -50, zoom: 0.9 } }; } // Export all examples as a list export const examples = [ srFlipFlop, srFlipFlopNand, dLatch, dFlipFlop ]; export function getExampleList() { return examples.map((fn, i) => { const ex = fn(); return { id: i, name: ex.name, description: ex.description }; }); } export function loadExample(index) { if (index < 0 || index >= examples.length) return null; const ex = examples[index](); return { circuit: { gates: JSON.parse(JSON.stringify(ex.gates)), connections: JSON.parse(JSON.stringify(ex.connections)), nextId: ex.nextId }, camera: ex.camera }; }