62 lines
2.1 KiB
Rust
62 lines
2.1 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
#![feature(type_alias_impl_trait)]
|
|
#![feature(impl_trait_in_assoc_type)]
|
|
|
|
// Simple 555-like oscillator implemented in firmware.
|
|
// - Q output: PB2 (also drives the on-board LED if present)
|
|
// - Combined Trigger/Threshold analog input: PA0 (capacitor node)
|
|
// Wiring suggestion:
|
|
// Q (PB2) --[R]--+-- C -- GND
|
|
// |
|
|
// PA0 (ADC input)
|
|
// The firmware toggles Q high when PA0 <= 1/3 Vref and low when PA0 >= 2/3 Vref.
|
|
|
|
use embassy_executor::Spawner;
|
|
use embassy_time::Timer;
|
|
use hal::gpio::{Level, Output};
|
|
use {ch32_hal as hal, panic_halt as _};
|
|
|
|
use hal::adc::{Adc, SampleTime};
|
|
|
|
#[embassy_executor::main(entry = "qingke_rt::entry")]
|
|
async fn main(_spawner: Spawner) -> ! {
|
|
let p = hal::init(Default::default());
|
|
|
|
// Q output on PB2
|
|
let mut q = Output::new(p.PB2, Level::Low, Default::default());
|
|
|
|
// ADC on PA0 for combined Trigger/Threshold input
|
|
let mut adc = Adc::new(p.ADC1, Default::default());
|
|
let mut trig_thres = p.PA0; // analog-capable pin used as ADC channel
|
|
|
|
// ADC characteristics: assume 12-bit if HAL doesn't expose it.
|
|
// If the HAL provides a method to query resolution, prefer that.
|
|
let full_scale: u16 = 4095; // 12-bit default
|
|
let thr_low: u16 = (full_scale as u32 / 3) as u16; // ~1/3 Vref
|
|
let thr_high: u16 = ((full_scale as u32 * 2) / 3) as u16; // ~2/3 Vref
|
|
|
|
// Start with Q low. State variable to avoid redundant toggles.
|
|
let mut q_high = false;
|
|
q.set_low();
|
|
|
|
loop {
|
|
// Read capacitor node voltage via ADC
|
|
let sample: u16 = adc.convert(&mut trig_thres, SampleTime::CYCLES239_5);
|
|
|
|
// Implement Schmitt trigger behavior like NE555 using thresholds
|
|
if !q_high && sample <= thr_low {
|
|
// Trigger: voltage fell below 1/3 Vref -> set output high
|
|
q.set_high();
|
|
q_high = true;
|
|
} else if q_high && sample >= thr_high {
|
|
// Threshold: voltage rose above 2/3 Vref -> set output low
|
|
q.set_low();
|
|
q_high = false;
|
|
}
|
|
|
|
// Small delay to reduce CPU usage; adjust for responsiveness/noise
|
|
Timer::after_micros(200).await;
|
|
}
|
|
}
|