use alloc::vec::Vec;
use onerom_config::hw::Board;
use onerom_metadata::OneromAlgPullConfig;
use crate::image::ChipSetType;
use super::addr_layout::AddrLayout;
fn encode_pull(gpio: u8, pull_up: bool) -> u8 {
if pull_up { 0x80 | gpio } else { gpio }
}
pub fn build_gpio_pull_config(
_layout: &AddrLayout,
set_type: ChipSetType,
num_chips: usize,
board: Board,
) -> Option<OneromAlgPullConfig> {
if !matches!(set_type, ChipSetType::Banked) {
return None;
}
let pull_up = board.x_jumper_pull() == 0;
let mut params: Vec<u8> = Vec::with_capacity(2);
for &gpio in board.gpios_for_x_pin(1) {
params.push(encode_pull(gpio, pull_up));
}
#[allow(clippy::collapsible_if)]
if num_chips >= 3 {
for &gpio in board.gpios_for_x_pin(2) {
params.push(encode_pull(gpio, pull_up));
}
}
if params.is_empty() {
None
} else {
Some(OneromAlgPullConfig { params })
}
}
#[cfg(test)]
mod tests {
use super::*;
fn layout_with_x(x1: u8, x2: u8) -> AddrLayout {
AddrLayout {
gpio_base: 0,
num_addr_pins: 16,
x1_gpio: Some(x1),
x2_gpio: Some(x2),
addr_pin_gpios: alloc::vec![7, 6, 5, 4, 3, 2, 1, 0, 10, 11, 14, 15, 12],
excess_addr_pin_gpios: alloc::vec![],
}
}
#[test]
fn banked_2bank_pulls_x1_only() {
let layout = layout_with_x(14, 15);
let pulls = build_gpio_pull_config(&layout, ChipSetType::Banked, 2, Board::Fire24A)
.expect("2-bank Banked set should have pull config");
assert_eq!(pulls.params, alloc::vec![encode_pull(9, true)]);
}
#[test]
fn banked_3bank_pulls_x1_and_x2() {
let layout = layout_with_x(14, 15);
let pulls = build_gpio_pull_config(&layout, ChipSetType::Banked, 3, Board::Fire24A)
.expect("3-bank Banked set should have pull config");
assert_eq!(
pulls.params,
alloc::vec![encode_pull(9, true), encode_pull(8, true)]
);
}
#[test]
fn banked_4bank_pulls_x1_and_x2() {
let layout = layout_with_x(14, 15);
let pulls = build_gpio_pull_config(&layout, ChipSetType::Banked, 4, Board::Fire24A)
.expect("4-bank Banked set should have pull config");
assert_eq!(
pulls.params,
alloc::vec![encode_pull(9, true), encode_pull(8, true)]
);
}
#[test]
fn single_no_pulls() {
let layout = AddrLayout {
gpio_base: 0,
num_addr_pins: 16,
x1_gpio: None,
x2_gpio: None,
addr_pin_gpios: alloc::vec![7, 6, 5, 4, 3, 2, 1, 0, 10, 11, 14, 15, 12],
excess_addr_pin_gpios: alloc::vec![],
};
let pulls = build_gpio_pull_config(&layout, ChipSetType::Single, 1, Board::Fire24A);
assert_eq!(pulls, None);
}
#[test]
fn multi_no_pulls() {
let layout = layout_with_x(14, 15);
let pulls = build_gpio_pull_config(&layout, ChipSetType::Multi, 3, Board::Fire24A);
assert_eq!(pulls, None);
}
}