libttl 0.1.1

A library for simulating TTL logic chips
Documentation
// examples/sr_latch.rs

use libttl::chips::Chip7400; // Only need NAND gates
use libttl::circuit::Circuit;
use libttl::logic_level::LogicLevel::{High, Low};
// use libttl::LogicLevel; // Already brought High/Low into scope

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Building Standard Active-Low SR Latch Circuit...");
    let mut circuit = Circuit::new();

    // Add Chips
    // Chip 0: 7400 (Quad NAND) - We'll use Gate 1 (pins 1,2 -> 3) and Gate 2 (pins 4,5 -> 6)
    let nand_chip_idx = circuit.add_chip(Box::new(Chip7400::new()));

    println!("Chip 0: 7400 (NAND)");

    // --- Wire the SR Latch (Cross-coupled NAND gates) ---
    // NAND1 Output (Pin 3, Q) -> NAND2 Input B (Pin 4)
    circuit.add_wire(nand_chip_idx, 3, nand_chip_idx, 4)?;
    // NAND2 Output (Pin 6, ~Q) -> NAND1 Input A (Pin 1)
    circuit.add_wire(nand_chip_idx, 6, nand_chip_idx, 1)?;

    // --- External Controls (Active LOW) ---
    // External signal '~S' (Set Bar) connects directly to NAND1 Input B (Pin 2)
    // External signal '~R' (Reset Bar) connects directly to NAND2 Input A (Pin 5)

    println!("\nWiring complete. Initial state (Hold: ~S=H, ~R=H):");
    // Set inputs to the stable Hold state initially
    circuit.set_external_input(nand_chip_idx, 2, High)?; // ~S = High
    circuit.set_external_input(nand_chip_idx, 5, High)?; // ~R = High

    println!("Running initial ticks to stabilize...");
    circuit.run(5); // Run a few ticks for signals to propagate and stabilize
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;      // Q is output of NAND1
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;  // ~Q is output of NAND2
    println!("Initial State (Hold): Q = {:?}, ~Q = {:?}", q, q_bar);
    // Note: Initial state of a simulated latch can be arbitrary (H/L or L/H)
    // before the first Set or Reset operation forces a known state.
    // Let's force it to RESET state first.

    // --- Simulation ---

    // Force Reset first: ~S=H, ~R=L => Q=L, ~Q=H
    println!("\nStep 1: Force initial RESET (~S=H, ~R=L)");
    circuit.set_external_input(nand_chip_idx, 2, High)?; // ~S = High
    circuit.set_external_input(nand_chip_idx, 5, Low)?;  // ~R = Low
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After Initial RESET: Q = {:?}, ~Q = {:?}", q, q_bar);
    assert_eq!(q, Low, "Initial Reset Failed (Q)");
    assert_eq!(q_bar, High, "Initial Reset Failed (~Q)");

    // Hold state after reset: ~S=H, ~R=H => Q=L, ~Q=H
    println!("\nStep 2: HOLD after RESET (~S=H, ~R=H)");
    circuit.set_external_input(nand_chip_idx, 2, High)?; // ~S = High
    circuit.set_external_input(nand_chip_idx, 5, High)?; // ~R = High
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After HOLD: Q = {:?}, ~Q = {:?}", q, q_bar);
    assert_eq!(q, Low, "Hold after Reset Failed (Q)"); // Should remain Low
    assert_eq!(q_bar, High, "Hold after Reset Failed (~Q)"); // Should remain High

    // Set the latch: ~S=L, ~R=H => Q=H, ~Q=L
    println!("\nStep 3: SET operation (~S=L, ~R=H)");
    circuit.set_external_input(nand_chip_idx, 2, Low)?;  // ~S = Low
    circuit.set_external_input(nand_chip_idx, 5, High)?; // ~R = High
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After SET: Q = {:?}, ~Q = {:?}", q, q_bar);
    assert_eq!(q, High, "Set Failed (Q)");
    assert_eq!(q_bar, Low, "Set Failed (~Q)");

    // Hold state after set: ~S=H, ~R=H => Q=H, ~Q=L
    println!("\nStep 4: HOLD after SET (~S=H, ~R=H)");
    circuit.set_external_input(nand_chip_idx, 2, High)?; // ~S = High
    circuit.set_external_input(nand_chip_idx, 5, High)?; // ~R = High
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After HOLD: Q = {:?}, ~Q = {:?}", q, q_bar);
    assert_eq!(q, High, "Hold after Set Failed (Q)"); // Should remain High
    assert_eq!(q_bar, Low, "Hold after Set Failed (~Q)"); // Should remain Low

     // Reset the latch: ~S=H, ~R=L => Q=L, ~Q=H
    println!("\nStep 5: RESET operation (~S=H, ~R=L)");
    circuit.set_external_input(nand_chip_idx, 2, High)?; // ~S = High
    circuit.set_external_input(nand_chip_idx, 5, Low)?;  // ~R = Low
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After RESET: Q = {:?}, ~Q = {:?}", q, q_bar);
    // This is the assertion that previously failed
    assert_eq!(q, Low, "Reset Failed (Q)");
    assert_eq!(q_bar, High, "Reset Failed (~Q)");

    // Invalid state: ~S=L, ~R=L => Q=H, ~Q=H
    println!("\nStep 6: INVALID state (~S=L, ~R=L)");
    circuit.set_external_input(nand_chip_idx, 2, Low)?; // ~S = Low
    circuit.set_external_input(nand_chip_idx, 5, Low)?; // ~R = Low
    circuit.tick();
    circuit.run(5);
    circuit.print_state();
    let q = circuit.get_output_level(nand_chip_idx, 3)?;
    let q_bar = circuit.get_output_level(nand_chip_idx, 6)?;
    println!("After INVALID: Q = {:?}, ~Q = {:?}", q, q_bar);
    assert_eq!(q, High, "Invalid State Failed (Q)");
    assert_eq!(q_bar, High, "Invalid State Failed (~Q)");

    println!("\nStandard SR Latch simulation complete.");
    Ok(())
}