use crate::chip::ChipType;
use crate::hw::Board;
#[derive(Clone, Copy, Debug)]
pub struct BoardPinMap {
pins: [u8; 40],
chip_pins: u8,
led_gpio: u8,
_board: Board,
}
impl BoardPinMap {
pub fn new(board: Board) -> Self {
let ref_chip = reference_chip(board.chip_pins());
let mut pins = [255u8; 40];
let chip_addr_phys = ref_chip.address_pins();
let board_addr_gpios = board.addr_pins();
debug_assert!(
chip_addr_phys.len() <= board_addr_gpios.len(),
"board addr_pins shorter than reference chip address line count"
);
for n in 0..chip_addr_phys.len() {
set_pin(&mut pins, chip_addr_phys[n], board_addr_gpios[n]);
}
let chip_data_phys = ref_chip.data_pins();
let board_data_gpios = board.data_pins();
debug_assert!(
chip_data_phys.len() <= board_data_gpios.len(),
"board data_pins shorter than reference chip data line count"
);
for n in 0..chip_data_phys.len() {
set_pin(&mut pins, chip_data_phys[n], board_data_gpios[n]);
}
for ctrl in ref_chip.control_lines() {
let gpio = board_gpio_for_control(board, ref_chip, ctrl.name);
if gpio != 255 {
set_pin(&mut pins, ctrl.pin, gpio);
}
}
if let Some(prog_pins) = ref_chip.programming_pins() {
for spec in prog_pins {
if let Some(gpio) = board.alt_pin(&ref_chip, spec.name) {
set_pin(&mut pins, spec.pin, gpio);
}
}
}
Self {
pins,
chip_pins: board.chip_pins(),
led_gpio: board.pin_status(),
_board: board,
}
}
pub fn gpio_for_chip_pin(&self, physical_pin: u8) -> Option<u8> {
if physical_pin == 0 || physical_pin as usize > self.chip_pins as usize {
return None;
}
match self.pins[physical_pin as usize - 1] {
255 => None,
gpio => Some(gpio),
}
}
pub fn chip_pins(&self) -> u8 {
self.chip_pins
}
pub fn led_gpio(&self) -> Option<u8> {
match self.led_gpio {
255 => None,
gpio => Some(gpio),
}
}
pub fn iter(&self) -> impl Iterator<Item = (u8, u8)> + '_ {
self.pins[..self.chip_pins as usize]
.iter()
.enumerate()
.filter_map(|(i, &gpio)| {
if gpio != 255 {
Some((i as u8 + 1, gpio))
} else {
None
}
})
}
}
fn reference_chip(chip_pins: u8) -> ChipType {
match chip_pins {
24 => ChipType::Chip2364,
28 => ChipType::Chip27512,
32 => ChipType::Chip27C040,
40 => ChipType::Chip27C400,
n => panic!("no reference chip defined for {}-pin socket", n),
}
}
fn board_gpio_for_control(board: Board, chip: ChipType, name: &str) -> u8 {
match name {
"ce" => board.pin_ce(chip),
"oe" => board.pin_oe(chip),
"cs1" => board.pin_cs1(chip),
"cs2" => board.pin_cs2(chip),
"cs3" => board.pin_cs3(chip),
"byte" => board.pin_byte(),
_ => 255,
}
}
#[inline]
fn set_pin(pins: &mut [u8; 40], physical_pin: u8, gpio: u8) {
if (1..=40).contains(&physical_pin) {
pins[physical_pin as usize - 1] = gpio;
}
}