#![no_main]
#![no_std]
use core::cell::{Cell, RefCell};
use cortex_m::peripheral::NVIC;
use cortex_m_rt::entry;
use critical_section::{with, Mutex};
use stm32_hal::{
adc::{Adc, AdcChannel, AdcDevice},
clocks::Clocks,
gpio::{Edge, Pin, PinMode, Port},
low_power,
pac::{self, interrupt, ADC1, EXTI},
rtc::{Rtc, RtcClockSource, RtcConfig},
timer::{Timer, TimerInterrupt},
};
static SENSOR_READING: Mutex<Cell<f32>> = Mutex::new(Cell::new(335.));
static BOUNCING: Mutex<Cell<bool>> = Mutex::new(Cell::new(false));
static ADC: Mutex<RefCell<Option<ADC<ADC1>>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let mut cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let clock_cfg = Clocks::default();
clock_cfg.setup().unwrap();
let mut button = Pin::new(Port::A, 0, PinMode::Input);
button.enable_interrupt(Edge::Falling);
let mut timer = Timer::new_tim3(dp.TIM3, 0.2, Default::default(), &clock_cfg);
timer.enable_interrupt(TimerInterrupt::Update); timer.enable();
let mut debounce_timer = Timer::new_tim15(dp.TIM15, 5., Default::default(), &clock_cfg);
debounce_timer.enable_interrupt(TimerInterrupt::Update);
let mut rtc = Rtc::new(
dp.RTC,
&mut dp.PWR,
RtcConfig {
clock_source: RtcClockSource::Lse,
..Default::default()
},
);
rtc.set_wakeup(&mut dp.EXTI, 30.);
let mut adc = Adc::new_adc1(
dp.ADC1,
AdcDevice::One,
Default::default(),
clock_cfg.systick(),
);
adc.enable_interrupt(AdcInterrupt::EndOfConversion);
with(|cs| {
ADC.borrow(cs).replace(Some(adc));
});
unsafe {
NVIC::unmask(pac::Interrupt::EXTI0); NVIC::unmask(pac::Interrupt::TIM3); NVIC::unmask(pac::Interrupt::TIM15); NVIC::unmask(pac::Interrupt::RTC_WKUP);
cp.NVIC.set_priority(pac::Interrupt::EXTI0, 0);
cp.NVIC.set_priority(pac::Interrupt::TIM3, 1);
}
loop {
low_power::stop(low_power::StopMode::Two);
clocks.reselect_input();
}
}
#[interrupt]
fn EXTI0() {
gpio::clear_exti_interrupt(0);
with(|cs| {
let bouncing = BOUNCING.borrow(cs);
if bouncing.get() {
return;
}
unsafe { (*pac::TIM15::ptr()).cr1.modify(|_, w| w.cen().set_bit()) }
bouncing.set(true);
let mut s = ADC.borrow(cs).borrow_mut();
let sensor = s.as_mut().unwrap();
let reading = sensor.read(AdcChannel::C1).unwrap();
SENSOR_READING.borrow(cs).replace(reading);
});
}
#[interrupt]
fn RTC_WKUP() {
with(|cs| {
unsafe {
gpio::clear_exti_interrupt(20);
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0xCA));
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0x53));
(*pac::RTC::ptr()).cr.modify(|_, w| w.wute().clear_bit());
(*pac::RTC::ptr()).isr.modify(|_, w| w.wutf().clear_bit());
(*pac::RTC::ptr()).cr.modify(|_, w| w.wute().set_bit());
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0xFF));
}
});
}
#[interrupt]
fn TIM3() {
with(|cs| {
unsafe { (*pac::TIM3::ptr()).sr.modify(|_, w| w.uif().clear_bit()) }
});
}
#[interrupt]
fn TIM15() {
with(|cs| {
unsafe { (*pac::TIM15::ptr()).sr.modify(|_, w| w.uif().clear_bit()) }
BOUNCING.borrow(cs).set(false);
unsafe { (*pac::TIM15::ptr()).cr1.modify(|_, w| w.cen().clear_bit()) }
});
}
#[defmt::panic_handler]
fn panic() -> ! {
cortex_m::asm::udf()
}