use crate::chips::common::{validate_pin, Chip, PinType};
use crate::gates::{Gate, NotGate};
use crate::logic_level::LogicLevel;
const PIN_COUNT_7404: usize = 14;
#[derive(Debug, Clone)]
pub struct Chip7404 {
pin_state: Vec<LogicLevel>,
gates: [NotGate; 6],
}
impl Chip7404 {
pub fn new() -> Self {
let mut pin_state = vec![LogicLevel::Low; PIN_COUNT_7404 + 1];
pin_state[14] = LogicLevel::High; pin_state[7] = LogicLevel::Low;
Chip7404 {
pin_state,
gates: [
NotGate::new(), NotGate::new(), NotGate::new(),
NotGate::new(), NotGate::new(), NotGate::new(),
],
}
}
}
impl Default for Chip7404 {
fn default() -> Self {
Self::new()
}
}
impl Chip for Chip7404 {
fn name(&self) -> &'static str { "7404" }
fn pin_count(&self) -> usize { PIN_COUNT_7404 }
fn get_pin_type(&self, pin: usize) -> PinType {
validate_pin(pin, self.pin_count());
match pin {
1 | 3 | 5 | 9 | 11 | 13 => PinType::Input,
2 | 4 | 6 | 8 | 10 | 12 => PinType::Output,
14 => PinType::Vcc,
7 => PinType::Gnd,
_ => unreachable!("Invalid pin {} for 7404 checked by validate_pin", pin), }
}
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 7404", 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 7404", pin);
match pin {
2 => self.gates[0].get_output(0),
4 => self.gates[1].get_output(0),
6 => self.gates[2].get_output(0),
8 => self.gates[3].get_output(0),
10 => self.gates[4].get_output(0),
12 => self.gates[5].get_output(0),
_ => unreachable!(),
}
}
fn update(&mut self) {
self.gates[0].update(&[self.pin_state[1]]);
self.pin_state[2] = self.gates[0].get_output(0);
self.gates[1].update(&[self.pin_state[3]]);
self.pin_state[4] = self.gates[1].get_output(0);
self.gates[2].update(&[self.pin_state[5]]);
self.pin_state[6] = self.gates[2].get_output(0);
self.gates[3].update(&[self.pin_state[9]]);
self.pin_state[8] = self.gates[3].get_output(0);
self.gates[4].update(&[self.pin_state[11]]);
self.pin_state[10] = self.gates[4].get_output(0);
self.gates[5].update(&[self.pin_state[13]]);
self.pin_state[12] = self.gates[5].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())
}
}