use num_enum::TryFromPrimitive;
use super::hal::{
gpio::{gpiod::*, gpioe::*, gpiof::*, gpiog::*, ErasedPin, Input, Output, PushPull},
hal::digital::v2::PinState,
};
use crate::net::serde::Serialize;
use defmt::Format;
use super::OutputChannelIdx;
#[allow(clippy::type_complexity)]
pub struct GpioPins {
pub hwrev: [ErasedPin<Input>; 4],
pub led: [ErasedPin<Output>; 8],
pub shdn: [ErasedPin<Output>; 4],
pub poe_pwr: PF2<Input>,
pub at_event: PE7<Input>,
pub eem_pwr: PD0<Output<PushPull>>,
pub tec_freq: PD2<Output<PushPull>>,
pub overtemp: PG12<Input>,
}
#[derive(Copy, Clone, Debug)]
pub enum State {
Assert,
Deassert,
}
impl From<bool> for State {
fn from(other: bool) -> State {
match other {
true => State::Assert,
false => State::Deassert,
}
}
}
impl From<State> for PinState {
fn from(other: State) -> PinState {
match other {
State::Assert => PinState::High,
State::Deassert => PinState::Low,
}
}
}
#[derive(Copy, Clone, Debug, Serialize, Format)]
pub enum PoePower {
Absent,
Low,
High,
}
impl Default for PoePower {
fn default() -> Self {
Self::Absent
}
}
#[derive(Copy, Clone, Debug)]
pub enum TecFrequency {
Low,
High,
}
impl From<TecFrequency> for PinState {
fn from(other: TecFrequency) -> PinState {
match other {
TecFrequency::Low => PinState::Low,
TecFrequency::High => PinState::High,
}
}
}
#[derive(Copy, Clone, Debug, TryFromPrimitive)]
#[repr(usize)]
pub enum Led {
Led0 = 0,
Led1 = 1,
Led2 = 2,
Led3 = 3,
Led4 = 4,
Led5 = 5,
Led6 = 6,
Led7 = 7,
}
pub struct Gpio {
pins: GpioPins,
}
impl Gpio {
pub fn new(pins: GpioPins) -> Self {
let mut gpio = Gpio { pins };
for i in 0..4 {
let ch = OutputChannelIdx::try_from(i).unwrap();
gpio.set_shutdown(ch, State::Assert);
}
for i in 0..8 {
gpio.set_led(Led::try_from(i).unwrap(), State::Deassert);
}
gpio.set_eem_pwr(false);
gpio.set_tec_frequency(TecFrequency::Low);
gpio
}
pub fn set_shutdown(&mut self, ch: OutputChannelIdx, shutdown: State) {
self.pins.shdn[ch as usize].set_state(!PinState::from(shutdown));
}
pub fn set_led(&mut self, led: Led, state: State) {
self.pins.led[led as usize].set_state(PinState::from(state));
}
pub fn hwrev(&self) -> u8 {
self.pins
.hwrev
.iter()
.enumerate()
.map(|(i, p)| (p.is_high() as u8) << i)
.sum()
}
pub fn poe(&self) -> PoePower {
match (self.pins.poe_pwr.is_high(), self.pins.at_event.is_high()) {
(false, _) => PoePower::Absent,
(true, false) => PoePower::Low,
(true, true) => PoePower::High,
}
}
pub fn set_eem_pwr(&mut self, enabled: bool) {
self.pins.eem_pwr.set_state(enabled.into());
}
pub fn set_tec_frequency(&mut self, frequency: TecFrequency) {
self.pins.tec_freq.set_state(frequency.into());
}
pub fn overtemp(&self) -> bool {
self.pins.overtemp.is_low()
}
}