use crate::args::{BoardHeaderArgs, BoardListArgs, BoardSocketArgs};
use crate::board_view::{render_pin_header, render_rom_socket};
use crate::utils::{get_reference_boards, get_supported_boards, resolve_board};
use onerom_cli::{Error, Options};
use onerom_config::chip::ChipType;
use onerom_config::hw::Board;
pub async fn cmd_list(_options: &Options, _args: &BoardListArgs) -> Result<(), Error> {
print_board_types();
Ok(())
}
pub(crate) fn print_board_types() {
println!("Supported One ROM board types:");
println!(" {}", get_supported_boards());
println!();
println!("Recognised, but not supported by the CLI:");
println!(" {}", get_reference_boards());
println!(" These boards use an STM32, rather than the RP2350 the CLI works with.");
}
pub async fn cmd_header(options: &Options, args: &BoardHeaderArgs) -> Result<(), Error> {
let board = resolve_board(options, &args.board)?.ok_or(Error::NoBoardOrDevice)?;
show_pin_header(&board);
Ok(())
}
pub async fn cmd_socket(options: &Options, args: &BoardSocketArgs) -> Result<(), Error> {
let board = resolve_board(options, &args.board)?.ok_or(Error::NoBoardOrDevice)?;
show_rom_socket(&board, &args.chip_type, args.gpio)
}
pub(crate) fn show_pin_header(board: &Board) {
match render_pin_header(board) {
Some(diagram) => print!("{diagram}"),
None => println!(
"Board {} has no pin-header descriptor - command unsupported.",
board.name()
),
}
}
pub(crate) fn show_rom_socket(
board: &Board,
chip_type: &Option<String>,
gpio: bool,
) -> Result<(), Error> {
if view_needs_gpios(chip_type, gpio) && board.socket_pin_map().is_empty() {
println!(
"Board {} has no GPIO map - command unsupported.",
board.name()
);
return Ok(());
}
let chip = match chip_type {
Some(t) => Some(resolve_socket_chip(board, t)?),
None => None,
};
print!("{}", render_rom_socket(board, chip, gpio));
Ok(())
}
fn view_needs_gpios(chip_type: &Option<String>, gpio: bool) -> bool {
chip_type.is_none() || gpio
}
fn resolve_socket_chip(board: &Board, name: &str) -> Result<ChipType, Error> {
let supported = onerom_cli::slot::emulatable_chip_names(board).join(", ");
let chip = ChipType::try_from_str(name)
.ok_or_else(|| Error::UnsupportedChipType(name.to_string(), supported.clone()))?;
if chip.chip_pins() == 0 {
return Err(Error::UnsupportedChipType(name.to_string(), supported));
}
if onerom_gen::compat::check_chip_set_on_board(
*board,
chip,
onerom_gen::ChipSetType::Single,
1,
onerom_gen::compat::default_cs_config(chip),
)
.is_err()
{
return Err(Error::UnsupportedChipType(name.to_string(), supported));
}
Ok(chip)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn only_the_gpio_views_need_the_socket_map() {
assert!(view_needs_gpios(&None, false));
assert!(view_needs_gpios(&None, true));
assert!(view_needs_gpios(&Some("2364".to_string()), true));
assert!(!view_needs_gpios(&Some("2364".to_string()), false));
}
#[test]
fn boards_without_a_socket_map_are_the_ones_that_cannot_draw_gpios() {
use onerom_config::hw::{BOARDS, Model};
for board in BOARDS {
assert_eq!(
board.socket_pin_map().is_empty(),
board.model() == Model::Ice,
"{} socket map",
board.name()
);
}
}
#[test]
fn socket_chip_rejects_plugins_and_zero_pin_types() {
let board = Board::try_from_str("fire-24-f").unwrap();
assert!(resolve_socket_chip(&board, "SystemPlugin").is_err());
assert!(resolve_socket_chip(&board, "UserPlugin").is_err());
assert!(resolve_socket_chip(&board, "2364").is_ok());
assert!(resolve_socket_chip(&board, "2764").is_ok());
}
}