use crate::chips::common::{validate_pin, Chip, PinType};
use crate::gates::{Gate, NandGate};
use crate::logic_level::LogicLevel;
const PIN_COUNT_7400: usize = 14;
#[derive(Debug, Clone)]
pub struct Chip7400 {
pin_state: Vec<LogicLevel>,
gates: [NandGate; 4],
}
impl Chip7400 {
pub fn new() -> Self {
let mut pin_state = vec![LogicLevel::Low; PIN_COUNT_7400 + 1];
pin_state[14] = LogicLevel::High; pin_state[7] = LogicLevel::Low; pin_state[3] = LogicLevel::High;
pin_state[6] = LogicLevel::High;
pin_state[8] = LogicLevel::High;
pin_state[11] = LogicLevel::High;
Chip7400 {
pin_state,
gates: [NandGate::new(), NandGate::new(), NandGate::new(), NandGate::new()],
}
}
}
impl Default for Chip7400 {
fn default() -> Self {
Self::new()
}
}
impl Chip for Chip7400 {
fn name(&self) -> &'static str { "7400" }
fn pin_count(&self) -> usize { PIN_COUNT_7400 }
fn get_pin_type(&self, pin: usize) -> PinType {
validate_pin(pin, self.pin_count());
match pin {
1 | 2 | 4 | 5 | 9 | 10 | 12 | 13 => PinType::Input,
3 | 6 | 8 | 11 => PinType::Output,
14 => PinType::Vcc,
7 => PinType::Gnd,
_ => unreachable!(),
}
}
fn set_input(&mut self, pin: usize, level: LogicLevel) {
validate_pin(pin, self.pin_count());
assert_eq!(self.get_pin_type(pin), PinType::Input, "Pin {} is not an input pin on 7400", pin);
self.pin_state[pin] = level;
}
fn get_output(&self, pin: usize) -> LogicLevel {
validate_pin(pin, self.pin_count());
assert_eq!(self.get_pin_type(pin), PinType::Output, "Pin {} is not an output pin on 7400", pin);
match pin {
3 => self.gates[0].get_output(0),
6 => self.gates[1].get_output(0),
8 => self.gates[2].get_output(0),
11 => self.gates[3].get_output(0),
_ => unreachable!(),
}
}
fn update(&mut self) {
self.gates[0].update(&[self.pin_state[1], self.pin_state[2]]);
self.pin_state[3] = self.gates[0].get_output(0);
self.gates[1].update(&[self.pin_state[4], self.pin_state[5]]);
self.pin_state[6] = self.gates[1].get_output(0);
self.gates[2].update(&[self.pin_state[9], self.pin_state[10]]);
self.pin_state[8] = self.gates[2].get_output(0);
self.gates[3].update(&[self.pin_state[12], self.pin_state[13]]);
self.pin_state[11] = self.gates[3].get_output(0);
self.pin_state[14] = LogicLevel::High;
self.pin_state[7] = LogicLevel::Low;
}
fn box_clone(&self) -> Box<dyn Chip> {
Box::new(self.clone())
}
}