libttl 0.1.1

A library for simulating TTL logic chips
Documentation
//! Common definitions for chips, like PinType and the Chip trait.

use crate::logic_level::LogicLevel;
use std::fmt::Debug;

/// Defines the type or function of a chip pin.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PinType {
    Input,
    Output,
    Vcc, // Positive power supply
    Gnd, // Ground
    Nc,  // No Connection
}

/// Trait representing a TTL chip.
///
/// Chips are composed of internal gates and have external pins.
/// They maintain the state of their pins and update their outputs based on inputs.
/// The `update` method simulates one clock cycle or propagation delay step.
pub trait Chip: Debug + Send + Sync {
    /// Returns the total number of pins on the chip package.
    fn pin_count(&self) -> usize;

    /// Gets the type (Input, Output, Vcc, Gnd, Nc) of a specific pin.
    /// Pin numbers are typically 1-based, matching datasheets.
    ///
    /// # Arguments
    /// * `pin` - The 1-based pin number.
    ///
    /// # Panics
    /// Panics if the pin number is invalid (0 or > pin_count).
    fn get_pin_type(&self, pin: usize) -> PinType;

    /// Sets the logic level of an input pin.
    /// Pin numbers are 1-based.
    ///
    /// # Arguments
    /// * `pin` - The 1-based pin number.
    /// * `level` - The logic level to set.
    ///
    /// # Panics
    /// Panics if the pin number is invalid or if the specified pin is not an Input pin.
    fn set_input(&mut self, pin: usize, level: LogicLevel);

    /// Gets the current logic level of an output pin.
    /// Pin numbers are 1-based.
    ///
    /// # Arguments
    /// * `pin` - The 1-based pin number.
    ///
    /// # Panics
    /// Panics if the pin number is invalid or if the specified pin is not an Output pin.
    fn get_output(&self, pin: usize) -> LogicLevel;

    /// Updates the chip's internal state.
    /// This typically involves:
    /// 1. Reading the current state of input pins.
    /// 2. Propagating these levels through the internal gates.
    /// 3. Updating the state of the output pins based on the gate results.
    /// This method simulates a clock tick or propagation delay for combinational logic.
    fn update(&mut self);

    /// Returns the name of the chip (e.g., "7400").
    fn name(&self) -> &'static str;

    /// Creates a boxed clone of the chip.
    fn box_clone(&self) -> Box<dyn Chip>;
}

// Implement Clone for Box<dyn Chip>
impl Clone for Box<dyn Chip> {
    fn clone(&self) -> Self {
        self.box_clone()
    }
}

// Helper function to validate pin numbers
#[inline(always)]
pub(crate) fn validate_pin(pin: usize, max_pin: usize) {
    assert!(pin >= 1 && pin <= max_pin, "Invalid pin number: {}", pin);
}