use core::convert::Infallible;
pub use crate::ioconfig::{FilterClockSelect, FilterType, regs::FunctionSelect};
pub use crate::pins::{Pin, PinId};
pub use embedded_hal::digital::PinState;
pub use ll::{DynPinId, InterruptEdge, InterruptLevel, Port, Pull};
pub mod asynch;
pub mod ll;
pub mod regs;
#[derive(Debug)]
pub struct Output(ll::LowLevelGpio);
impl Output {
pub fn new<I: PinId>(_pin: Pin<I>, init_level: PinState) -> Self {
let mut ll = ll::LowLevelGpio::new(I::ID);
ll.configure_as_output_push_pull(init_level);
Output(ll)
}
#[inline]
pub fn port(&self) -> Port {
self.0.port()
}
#[inline]
pub fn offset(&self) -> usize {
self.0.offset()
}
#[inline]
pub fn set_high(&mut self) {
self.0.set_high();
}
#[inline]
pub fn set_state(&mut self, state: PinState) {
match state {
PinState::Low => self.set_low(),
PinState::High => self.set_high(),
}
}
#[inline]
pub fn set_low(&mut self) {
self.0.set_low();
}
#[inline]
pub fn is_set_high(&self) -> bool {
self.0.is_set_high()
}
#[inline]
pub fn is_set_low(&self) -> bool {
self.0.is_set_low()
}
#[inline]
pub fn toggle(&mut self) {
self.0.toggle();
}
#[inline]
pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) {
self.0.configure_pulse_mode(enable, default_state);
}
#[inline]
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
self.0.configure_delay(delay_1, delay_2);
}
}
impl embedded_hal::digital::ErrorType for Output {
type Error = Infallible;
}
impl embedded_hal::digital::OutputPin for Output {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.0.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.0.set_high();
Ok(())
}
}
impl embedded_hal::digital::StatefulOutputPin for Output {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.0.is_set_high())
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.0.is_set_low())
}
fn toggle(&mut self) -> Result<(), Self::Error> {
self.0.toggle();
Ok(())
}
}
#[derive(Debug)]
pub struct Input(ll::LowLevelGpio);
impl Input {
pub fn new_floating<I: PinId>(_pin: Pin<I>) -> Self {
let mut ll = ll::LowLevelGpio::new(I::ID);
ll.configure_as_input_floating();
Input(ll)
}
pub fn new_with_pull<I: PinId>(_pin: Pin<I>, pull: Pull) -> Self {
let mut ll = ll::LowLevelGpio::new(I::ID);
ll.configure_as_input_with_pull(pull);
Input(ll)
}
#[inline]
pub fn id(&self) -> DynPinId {
self.0.id()
}
#[inline]
pub fn enable_interrupt_gpio_only(&mut self) {
self.0.enable_interrupt_gpio_only();
}
#[cfg(feature = "vor1x")]
#[inline]
pub fn enable_interrupt(&mut self, irq_cfg: crate::InterruptConfig, gpio: bool) {
self.0.enable_interrupt(irq_cfg, gpio);
}
#[cfg(feature = "vor4x")]
#[inline]
pub fn enable_interrupt(
&mut self,
enable_in_nvic: bool,
gpio: bool,
) -> Result<(), ll::PortDoesNotSupportInterrupts> {
self.0.enable_interrupt(enable_in_nvic, gpio)
}
#[inline]
pub fn configure_edge_interrupt(&mut self, edge: InterruptEdge) {
self.0.configure_edge_interrupt(edge);
}
#[inline]
pub fn configure_level_interrupt(&mut self, edge: InterruptLevel) {
self.0.configure_level_interrupt(edge);
}
#[inline]
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
self.0.configure_delay(delay_1, delay_2);
}
#[inline]
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClockSelect) {
self.0.configure_filter_type(filter, clksel);
}
#[inline]
pub fn is_low(&self) -> bool {
self.0.is_low()
}
#[inline]
pub fn is_high(&self) -> bool {
self.0.is_high()
}
}
impl embedded_hal::digital::ErrorType for Input {
type Error = Infallible;
}
impl embedded_hal::digital::InputPin for Input {
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.0.is_low())
}
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.0.is_high())
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PinMode {
InputFloating,
InputWithPull(Pull),
OutputPushPull,
OutputOpenDrain,
}
impl PinMode {
pub fn is_input(&self) -> bool {
matches!(self, PinMode::InputFloating | PinMode::InputWithPull(_))
}
pub fn is_output(&self) -> bool {
!self.is_input()
}
}
#[derive(Debug)]
pub struct Flex {
ll: ll::LowLevelGpio,
mode: PinMode,
}
impl Flex {
pub fn new<I: PinId>(_pin: Pin<I>) -> Self {
let mut ll = ll::LowLevelGpio::new(I::ID);
ll.configure_as_input_floating();
Flex {
ll,
mode: PinMode::InputFloating,
}
}
#[inline]
pub fn port(&self) -> Port {
self.ll.port()
}
#[inline]
pub fn offset(&self) -> usize {
self.ll.offset()
}
#[inline]
pub fn is_low(&self) -> bool {
self.ll.is_low()
}
#[inline]
pub fn is_high(&self) -> bool {
self.ll.is_high()
}
#[inline]
pub fn set_low(&mut self) {
if !self.mode.is_input() {
return;
}
self.ll.set_low();
}
#[inline]
pub fn set_high(&mut self) {
if !self.mode.is_input() {
return;
}
self.ll.set_high();
}
#[inline]
pub fn set_state(&mut self, state: PinState) {
match state {
PinState::Low => self.set_low(),
PinState::High => self.set_high(),
}
}
}
impl embedded_hal::digital::ErrorType for Flex {
type Error = Infallible;
}
impl embedded_hal::digital::InputPin for Flex {
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.ll.is_low())
}
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.ll.is_high())
}
}
impl embedded_hal::digital::OutputPin for Flex {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_high();
Ok(())
}
}
impl embedded_hal::digital::StatefulOutputPin for Flex {
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.ll.is_set_high())
}
fn is_set_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.ll.is_set_low())
}
fn toggle(&mut self) -> Result<(), Self::Error> {
self.ll.toggle();
Ok(())
}
}
pub struct IoPeriphPin {
ll: ll::LowLevelGpio,
fun_sel: FunctionSelect,
}
impl IoPeriphPin {
pub fn new_with_pin<I: PinId>(
_pin: Pin<I>,
fun_sel: FunctionSelect,
pull: Option<Pull>,
) -> Self {
let mut ll = ll::LowLevelGpio::new(I::ID);
ll.configure_as_peripheral_pin(fun_sel, pull);
IoPeriphPin { ll, fun_sel }
}
pub fn new(pin_id: DynPinId, fun_sel: FunctionSelect, pull: Option<Pull>) -> Self {
let mut ll = ll::LowLevelGpio::new(pin_id);
ll.configure_as_peripheral_pin(fun_sel, pull);
IoPeriphPin { ll, fun_sel }
}
pub fn port(&self) -> Port {
self.ll.port()
}
pub fn offset(&self) -> usize {
self.ll.offset()
}
pub fn fun_sel(&self) -> FunctionSelect {
self.fun_sel
}
}