#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt_rtt as _;
use panic_halt as _;
use gd32e2_hal::pac;
use gd32e2_hal::prelude::*;
use gd32e2_hal::rcu::{ClockConfig, PllFreq, SysClk};
use gd32e2_hal::time::MicrosDuration;
use gd32e2_hal::timer::Edge;
const CAPTURE_PSC: u16 = 47;
const TOLERANCE_PERCENT: u32 = 5;
const SHAPES: [(u32, u32); 3] = [(250, 750), (1_000, 4_000), (5_000, 5_000)];
fn check(what: &str, measured: u32, expected: u32) {
let off_by = measured.abs_diff(expected) * 100 / expected.max(1);
if off_by <= TOLERANCE_PERCENT {
defmt::info!("{}: {} us, expected {} us : OK", what, measured, expected);
} else {
defmt::error!(
"{}: {} us, expected {} us : off by {} %",
what,
measured,
expected,
off_by
);
}
}
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut fmc = dp.fmc.constrain();
let config = ClockConfig::default().sysclk(SysClk::Pll(PllFreq::Mhz48));
let mut rcu = dp.rcu.constrain().freeze(&mut fmc, config);
let gpioa = dp.gpioa.split(&mut rcu);
let mut source = gpioa.pa2.into_push_pull_output();
let sense_pin = gpioa.pa3.into_alternate::<0>();
let mut delay = dp.timer5.constrain(&mut rcu).into_delay();
let mut capture = dp.timer14.constrain(&mut rcu).into_capture(CAPTURE_PSC);
let mut sense = capture.channel(sense_pin, Edge::Rising);
sense.enable();
defmt::info!("driving PA2, capturing PA3, 1 us per tick");
loop {
for (high, low) in SHAPES {
defmt::info!("--- {} us high, {} us low ---", high, low);
source.set_high();
let first = block!(sense.read());
delay.delay(MicrosDuration::from_micros(high));
source.set_low();
delay.delay(MicrosDuration::from_micros(low));
source.set_high();
let second = block!(sense.read());
match (first, second) {
(Ok(first), Ok(second)) => {
sense.select_edge(Edge::Falling);
delay.delay(MicrosDuration::from_micros(high));
source.set_low();
let fall = block!(sense.read());
sense.select_edge(Edge::Rising);
let period: MicrosDuration = sense.interval(first, second);
check("period", period.as_micros(), high + low);
match fall {
Ok(fall) => {
let width: MicrosDuration = sense.interval(second, fall);
check("width", width.as_micros(), high);
}
Err(_) => defmt::warn!("overcapture on the falling edge"),
}
}
_ => {
defmt::warn!("overcapture between the rising edges, skipping");
source.set_low();
}
}
delay.delay(MicrosDuration::from_micros(low));
}
}
}