#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct I2cBus {
pub id: u8,
pub sda_pin: u8,
pub scl_pin: u8,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BoardProfile {
pub name: &'static str,
pub gpio_pins: &'static [u8],
pub adc_pins: &'static [u8],
pub i2c_buses: &'static [I2cBus],
pub has_nvs: bool,
pub has_pwm: bool,
}
impl BoardProfile {
pub fn is_valid_gpio(&self, pin: u8) -> bool {
self.gpio_pins.contains(&pin)
}
pub fn is_valid_adc(&self, pin: u8) -> bool {
self.adc_pins.contains(&pin)
}
pub fn i2c_bus(&self, id: u8) -> Option<&I2cBus> {
self.i2c_buses.iter().find(|b| b.id == id)
}
}
pub const ESP32_PROFILE: BoardProfile = BoardProfile {
name: "esp32",
gpio_pins: &[
0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33, 34, 35,
36, 39,
],
adc_pins: &[32, 33, 34, 35, 36, 39],
i2c_buses: &[I2cBus {
id: 0,
sda_pin: 21,
scl_pin: 22,
}],
has_nvs: true,
has_pwm: true,
};
pub const RPI_PROFILE: BoardProfile = BoardProfile {
name: "rpi",
gpio_pins: &[
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27,
],
adc_pins: &[],
i2c_buses: &[I2cBus {
id: 1,
sda_pin: 2,
scl_pin: 3,
}],
has_nvs: false,
has_pwm: true,
};
pub fn profile_for(board_type: &str) -> Option<&'static BoardProfile> {
match board_type {
"esp32" => Some(&ESP32_PROFILE),
"rpi" => Some(&RPI_PROFILE),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_esp32_profile_name() {
assert_eq!(ESP32_PROFILE.name, "esp32");
}
#[test]
fn test_valid_gpio_pin() {
assert!(ESP32_PROFILE.is_valid_gpio(21));
assert!(ESP32_PROFILE.is_valid_gpio(0));
assert!(ESP32_PROFILE.is_valid_gpio(39));
}
#[test]
fn test_invalid_gpio_pin() {
assert!(!ESP32_PROFILE.is_valid_gpio(100));
assert!(!ESP32_PROFILE.is_valid_gpio(6)); assert!(!ESP32_PROFILE.is_valid_gpio(255));
}
#[test]
fn test_valid_adc_pin() {
assert!(ESP32_PROFILE.is_valid_adc(32));
assert!(ESP32_PROFILE.is_valid_adc(36));
assert!(ESP32_PROFILE.is_valid_adc(39));
}
#[test]
fn test_invalid_adc_pin() {
assert!(!ESP32_PROFILE.is_valid_adc(21));
assert!(!ESP32_PROFILE.is_valid_adc(22));
assert!(!ESP32_PROFILE.is_valid_adc(100));
}
#[test]
fn test_i2c_bus_lookup() {
let bus = ESP32_PROFILE.i2c_bus(0).expect("bus 0 should exist");
assert_eq!(bus.id, 0);
assert_eq!(bus.sda_pin, 21);
assert_eq!(bus.scl_pin, 22);
assert!(ESP32_PROFILE.i2c_bus(1).is_none());
}
#[test]
fn test_esp32_capabilities() {
assert!(ESP32_PROFILE.has_nvs);
assert!(ESP32_PROFILE.has_pwm);
}
#[test]
fn test_profile_for_known_board() {
let profile = profile_for("esp32").expect("esp32 should be known");
assert_eq!(profile.name, "esp32");
}
#[test]
fn test_profile_for_unknown_board() {
assert!(profile_for("stm32f4").is_none());
assert!(profile_for("").is_none());
assert!(profile_for("ESP32").is_none()); }
#[test]
fn test_esp32_gpio_pin_count() {
assert_eq!(ESP32_PROFILE.gpio_pins.len(), 26);
}
#[test]
fn test_rpi_profile_name() {
assert_eq!(RPI_PROFILE.name, "rpi");
}
#[test]
fn test_rpi_valid_gpio_pins() {
for pin in 2..=27 {
assert!(
RPI_PROFILE.is_valid_gpio(pin),
"GPIO {} should be valid",
pin
);
}
}
#[test]
fn test_rpi_invalid_gpio_pins() {
assert!(!RPI_PROFILE.is_valid_gpio(0));
assert!(!RPI_PROFILE.is_valid_gpio(1));
assert!(!RPI_PROFILE.is_valid_gpio(28));
assert!(!RPI_PROFILE.is_valid_gpio(100));
}
#[test]
fn test_rpi_no_adc() {
assert!(RPI_PROFILE.adc_pins.is_empty());
assert!(!RPI_PROFILE.is_valid_adc(2));
}
#[test]
fn test_rpi_i2c_bus_1() {
let bus = RPI_PROFILE.i2c_bus(1).expect("bus 1 should exist");
assert_eq!(bus.sda_pin, 2);
assert_eq!(bus.scl_pin, 3);
assert!(RPI_PROFILE.i2c_bus(0).is_none());
}
#[test]
fn test_rpi_capabilities() {
assert!(!RPI_PROFILE.has_nvs);
assert!(RPI_PROFILE.has_pwm);
}
#[test]
fn test_rpi_gpio_pin_count() {
assert_eq!(RPI_PROFILE.gpio_pins.len(), 26);
}
#[test]
fn test_profile_for_rpi() {
let profile = profile_for("rpi").expect("rpi should be known");
assert_eq!(profile.name, "rpi");
}
}