libttl 0.1.1

A library for simulating TTL logic chips
Documentation
#![allow(dead_code)] // Allow unused helper functions

use libttl::chips::{Chip, PinType};
use libttl::logic_level::LogicLevel::{High, Low};
use libttl::LogicLevel;

// --- Test Helpers ---

pub fn test_pin_types(chip: &dyn Chip, expected_types: &[(usize, PinType)]) {
    assert!(chip.pin_count() >= *expected_types.iter().map(|(p, _)| p).max().unwrap_or(&0));

    for (pin, expected_type) in expected_types {
        assert_eq!(
            chip.get_pin_type(*pin),
            *expected_type,
            "Pin {} type mismatch for chip {}", chip.name(), pin
        );
    }
    // Check standard pins
     assert_eq!(chip.get_pin_type(chip.pin_count()), PinType::Vcc, "Vcc pin type mismatch for {}", chip.name());
     assert_eq!(chip.get_pin_type(7), PinType::Gnd, "Gnd pin type mismatch for {}", chip.name());
}

pub fn test_logic_2_input_1_output(
    chip: &mut dyn Chip,
    pin_a: usize,
    pin_b: usize,
    pin_y: usize,
    gate_logic: fn(LogicLevel, LogicLevel) -> LogicLevel,
) {
    println!("Testing gate: A={}, B={}, Y={} on {}", pin_a, pin_b, pin_y, chip.name());
    let inputs = [(Low, Low), (Low, High), (High, Low), (High, High)];

    for (in_a, in_b) in inputs {
        chip.set_input(pin_a, in_a);
        chip.set_input(pin_b, in_b);
        chip.update(); // Simulate clock tick / propagation
        let expected_y = gate_logic(in_a, in_b);
        let actual_y = chip.get_output(pin_y);
        assert_eq!(
            actual_y, expected_y,
            "Chip {} Gate (A={}, B={}, Y={}): Input ({:?}, {:?}) -> Expected {:?}, Got {:?}",
            chip.name(), pin_a, pin_b, pin_y, in_a, in_b, expected_y, actual_y
        );
    }
}

pub fn test_logic_1_input_1_output(
    chip: &mut dyn Chip,
    pin_a: usize,
    pin_y: usize,
    gate_logic: fn(LogicLevel) -> LogicLevel,
) {
     println!("Testing gate: A={}, Y={} on {}", pin_a, pin_y, chip.name());
    let inputs = [Low, High];

    for in_a in inputs {
        chip.set_input(pin_a, in_a);
        chip.update(); // Simulate clock tick / propagation
        let expected_y = gate_logic(in_a);
        let actual_y = chip.get_output(pin_y);
        assert_eq!(
            actual_y, expected_y,
            "Chip {} Gate (A={}, Y={}): Input ({:?}) -> Expected {:?}, Got {:?}",
            chip.name(), pin_a, pin_y, in_a, expected_y, actual_y
        );
    }
}

#[test]
#[should_panic]
fn test_chip_invalid_pin_get_type() {
    let chip = libttl::chips::Chip7400::new();
    chip.get_pin_type(0);
}

#[test]
#[should_panic]
fn test_chip_invalid_pin_set_input() {
    let mut chip = libttl::chips::Chip7400::new();
    chip.set_input(15, Low);
}

#[test]
#[should_panic]
fn test_chip_set_input_on_output_pin() {
    let mut chip = libttl::chips::Chip7400::new();
    chip.set_input(3, Low); // Pin 3 is an output
}

#[test]
#[should_panic]
fn test_chip_get_output_on_input_pin() {
    let chip = libttl::chips::Chip7400::new();
    chip.get_output(1); // Pin 1 is an input
}