use embedded_hal::delay::DelayNs;
use crate::driver::error::{IoError, Result};
use crate::internal::constants::{RESET_POLL_INTERVAL_US, SOFT_RESET_TIMEOUT_MS};
use crate::internal::register::dma::{DMABUSMODE_SW_RST, DmaRegs};
use crate::internal::register::ext::ExtRegs;
#[derive(Debug)]
pub struct ResetController<D: DelayNs> {
delay: D,
timeout_ms: u32,
}
impl<D: DelayNs> ResetController<D> {
pub fn new(delay: D) -> Self {
Self {
delay,
timeout_ms: SOFT_RESET_TIMEOUT_MS,
}
}
pub fn with_timeout(delay: D, timeout_ms: u32) -> Self {
Self { delay, timeout_ms }
}
pub fn soft_reset(&mut self) -> Result<()> {
let bus_mode = DmaRegs::bus_mode();
DmaRegs::set_bus_mode(bus_mode | DMABUSMODE_SW_RST);
let max_iterations = (self.timeout_ms * 1000) / RESET_POLL_INTERVAL_US;
for _ in 0..max_iterations {
if !self.is_reset_in_progress() {
return Ok(());
}
self.delay.delay_us(RESET_POLL_INTERVAL_US);
}
Err(IoError::Timeout.into())
}
pub fn is_reset_in_progress(&self) -> bool {
(DmaRegs::bus_mode() & DMABUSMODE_SW_RST) != 0
}
pub fn is_reset_done(&self) -> bool {
!self.is_reset_in_progress()
}
pub fn power_up(&self) {
ExtRegs::power_up_ram();
}
pub fn power_down(&self) {
ExtRegs::power_down_ram();
}
pub fn timeout_ms(&self) -> u32 {
self.timeout_ms
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ResetState {
#[default]
Normal,
Resetting,
ResetComplete,
}
#[derive(Debug)]
pub struct ResetManager<D: DelayNs> {
controller: ResetController<D>,
state: ResetState,
}
impl<D: DelayNs> ResetManager<D> {
pub fn new(delay: D) -> Self {
Self {
controller: ResetController::new(delay),
state: ResetState::Normal,
}
}
pub fn state(&self) -> ResetState {
self.state
}
pub fn start_reset(&mut self) {
let bus_mode = DmaRegs::bus_mode();
DmaRegs::set_bus_mode(bus_mode | DMABUSMODE_SW_RST);
self.state = ResetState::Resetting;
}
pub fn poll_reset(&mut self) -> bool {
if self.state == ResetState::Resetting && self.controller.is_reset_done() {
self.state = ResetState::ResetComplete;
true
} else {
self.state == ResetState::ResetComplete
}
}
pub fn reset(&mut self) -> Result<()> {
self.start_reset();
let result = self.controller.soft_reset();
if result.is_ok() {
self.state = ResetState::ResetComplete;
} else {
self.state = ResetState::Normal; }
result
}
pub fn complete(&mut self) {
self.state = ResetState::Normal;
}
pub fn controller(&self) -> &ResetController<D> {
&self.controller
}
pub fn controller_mut(&mut self) -> &mut ResetController<D> {
&mut self.controller
}
}
pub fn full_reset<D: DelayNs>(mut delay: D, timeout_ms: u32) -> Result<()> {
ExtRegs::power_up_ram();
delay.delay_us(10);
let mut reset_ctrl = ResetController::with_timeout(delay, timeout_ms);
reset_ctrl.soft_reset()
}