use onerom_metadata::{GPIO_NONE, OneromAlgCsConfig, OneromAlgDataConfig};
use crate::image::ChipSetType;
use super::alg_config::{DEFAULT_CLKDIV_FRAC, DEFAULT_CLKDIV_INT};
use super::cs_data_layout::CsDataLayout;
fn serve_cs_low_0(set_type: ChipSetType) -> u8 {
match set_type {
ChipSetType::Single | ChipSetType::Banked => 0,
ChipSetType::Multi => 1,
}
}
fn first_rom_cs(layout: &CsDataLayout, set_type: ChipSetType) -> (u8, u8) {
match set_type {
ChipSetType::Single | ChipSetType::Banked => (layout.base_cs_pin, layout.num_cs_pins),
ChipSetType::Multi => {
let chip0_select = layout
.select_lines
.first()
.expect("Multi sets must have at least one select line");
(chip0_select.gpio - layout.gpio_base, 1)
}
}
}
pub fn build_alg_cs(
layout: &CsDataLayout,
set_type: ChipSetType,
alg_data: &OneromAlgDataConfig,
) -> OneromAlgCsConfig {
if let Some(cs2) = &layout.alg_cs2 {
return OneromAlgCsConfig::AlgCs2 {
clkdiv_int: DEFAULT_CLKDIV_INT,
clkdiv_frac: DEFAULT_CLKDIV_FRAC,
gpio_base: layout.gpio_base,
base_cs_pin: layout.base_cs_pin,
num_cs_pins: layout.num_cs_pins,
base_data_pin: layout.base_data_pin,
num_data_pins: layout.num_data_pins,
cs_active_delay: 0,
cs_inactive_delay: 0,
base_qualifier_pin: cs2.base_qualifier_pin,
num_qualifier_pins: cs2.num_qualifier_pins,
qualifier_inactive_pattern: cs2.qualifier_inactive_pattern,
};
}
match layout.cs_ignore_index {
None => {
let byte_pin = match alg_data {
OneromAlgDataConfig::AlgData1 { byte_pin, .. } => *byte_pin,
_ => GPIO_NONE,
};
let (first_rom_cs_base, first_rom_num_cs_pins) = first_rom_cs(layout, set_type);
OneromAlgCsConfig::AlgCs0 {
clkdiv_int: DEFAULT_CLKDIV_INT,
clkdiv_frac: DEFAULT_CLKDIV_FRAC,
gpio_base: layout.gpio_base,
base_cs_pin: layout.base_cs_pin,
num_cs_pins: layout.num_cs_pins,
base_data_pin: layout.base_data_pin,
num_data_pins: layout.num_data_pins,
cs_active_delay: 0,
cs_inactive_delay: 0,
serve_cs_low_0: serve_cs_low_0(set_type),
byte_pin,
first_rom_cs_base,
first_rom_num_cs_pins,
}
}
Some(cs_ignore_index) => OneromAlgCsConfig::AlgCs1 {
clkdiv_int: DEFAULT_CLKDIV_INT,
clkdiv_frac: DEFAULT_CLKDIV_FRAC,
gpio_base: layout.gpio_base,
base_cs_pin: layout.base_cs_pin,
num_cs_pins: layout.num_cs_pins,
base_data_pin: layout.base_data_pin,
num_data_pins: layout.num_data_pins,
cs_active_delay: 0,
cs_inactive_delay: 0,
cs_ignore_index,
},
}
}
#[cfg(test)]
mod tests {
use super::super::cs_data_layout::{AlgCs2Config, SelectLine, SelectRole};
use super::*;
fn fire24a_2364_layout() -> CsDataLayout {
CsDataLayout {
gpio_base: 0,
base_data_pin: 16,
num_data_pins: 8,
data_pin_gpios: alloc::vec![16, 17, 18, 19, 20, 21, 22, 23],
base_cs_pin: 13,
num_cs_pins: 1,
cs_ignore_index: None,
select_lines: alloc::vec![SelectLine {
role: SelectRole::Cs1,
gpio: 13
}],
commoned_lines: alloc::vec![],
alg_cs2: None,
}
}
fn alg_data_8bit() -> OneromAlgDataConfig {
OneromAlgDataConfig::AlgData0 {
clkdiv_int: 1,
clkdiv_frac: 0,
gpio_base: 0,
base_data_pin: 16,
word_size: 8,
}
}
#[test]
fn fire24a_2364_single() {
let layout = fire24a_2364_layout();
let alg_data = alg_data_8bit();
let alg_cs = build_alg_cs(&layout, ChipSetType::Single, &alg_data);
assert_eq!(
alg_cs,
OneromAlgCsConfig::AlgCs0 {
clkdiv_int: 1,
clkdiv_frac: 0,
gpio_base: 0,
base_cs_pin: 13,
num_cs_pins: 1,
base_data_pin: 16,
num_data_pins: 8,
cs_active_delay: 0,
cs_inactive_delay: 0,
serve_cs_low_0: 0,
byte_pin: GPIO_NONE,
first_rom_cs_base: 13,
first_rom_num_cs_pins: 1,
}
);
}
#[test]
fn multi_serve_cs_low_0_and_first_rom() {
let layout = CsDataLayout {
gpio_base: 0,
base_data_pin: 16,
num_data_pins: 8,
data_pin_gpios: alloc::vec![16, 17, 18, 19, 20, 21, 22, 23],
base_cs_pin: 13,
num_cs_pins: 3,
cs_ignore_index: None,
select_lines: alloc::vec![
SelectLine {
role: SelectRole::Cs1,
gpio: 13
},
SelectLine {
role: SelectRole::X1,
gpio: 14
},
SelectLine {
role: SelectRole::X2,
gpio: 15
},
],
commoned_lines: alloc::vec![],
alg_cs2: None,
};
let alg_data = alg_data_8bit();
let alg_cs = build_alg_cs(&layout, ChipSetType::Multi, &alg_data);
match alg_cs {
OneromAlgCsConfig::AlgCs0 {
clkdiv_int: _,
clkdiv_frac: _,
gpio_base: _,
base_cs_pin: _,
num_cs_pins: _,
base_data_pin: _,
num_data_pins: _,
cs_active_delay: _,
cs_inactive_delay: _,
serve_cs_low_0,
byte_pin: _,
first_rom_cs_base,
first_rom_num_cs_pins,
} => {
assert_eq!(serve_cs_low_0, 1);
assert_eq!(first_rom_cs_base, 13);
assert_eq!(first_rom_num_cs_pins, 1);
}
_ => panic!("expected AlgCs0"),
}
}
#[test]
fn fire24a_2316_cs2_active_alg_cs1() {
let layout = CsDataLayout {
gpio_base: 0,
base_data_pin: 16,
num_data_pins: 8,
data_pin_gpios: alloc::vec![16, 17, 18, 19, 20, 21, 22, 23],
base_cs_pin: 13,
num_cs_pins: 3,
cs_ignore_index: Some(1),
select_lines: alloc::vec![
SelectLine {
role: SelectRole::Cs1,
gpio: 13
},
SelectLine {
role: SelectRole::Cs2,
gpio: 15
},
],
commoned_lines: alloc::vec![],
alg_cs2: None,
};
let alg_data = alg_data_8bit();
let alg_cs = build_alg_cs(&layout, ChipSetType::Single, &alg_data);
assert_eq!(
alg_cs,
OneromAlgCsConfig::AlgCs1 {
clkdiv_int: 1,
clkdiv_frac: 0,
gpio_base: 0,
base_cs_pin: 13,
num_cs_pins: 3,
base_data_pin: 16,
num_data_pins: 8,
cs_active_delay: 0,
cs_inactive_delay: 0,
cs_ignore_index: 1,
}
);
}
#[test]
fn alg_cs2_layout_emits_alg_cs2() {
let layout = CsDataLayout {
gpio_base: 0,
base_data_pin: 16,
num_data_pins: 8,
data_pin_gpios: alloc::vec![16, 17, 18, 19, 20, 21, 22, 23],
base_cs_pin: 13,
num_cs_pins: 1,
cs_ignore_index: None,
select_lines: alloc::vec![SelectLine {
role: SelectRole::Cs1,
gpio: 13
}],
commoned_lines: alloc::vec![],
alg_cs2: Some(AlgCs2Config {
base_qualifier_pin: 5,
num_qualifier_pins: 2,
qualifier_inactive_pattern: 0b11,
}),
};
let alg_data = alg_data_8bit();
let alg_cs = build_alg_cs(&layout, ChipSetType::Single, &alg_data);
assert_eq!(
alg_cs,
OneromAlgCsConfig::AlgCs2 {
clkdiv_int: 1,
clkdiv_frac: 0,
gpio_base: 0,
base_cs_pin: 13,
num_cs_pins: 1,
base_data_pin: 16,
num_data_pins: 8,
cs_active_delay: 0,
cs_inactive_delay: 0,
base_qualifier_pin: 5,
num_qualifier_pins: 2,
qualifier_inactive_pattern: 0b11,
}
);
}
}