use crate::*;
pub struct DigitalPin<'a> {
avr: &'a mut AvrTester,
port: char,
pin: u8,
}
impl<'a> DigitalPin<'a> {
pub(crate) fn new(avr: &'a mut AvrTester, port: char, pin: u8) -> Self {
Self { avr, port, pin }
}
pub fn set(&mut self, high: bool) {
self.avr.sim().set_digital_pin(self.port, self.pin, high);
}
pub fn set_low(&mut self) {
self.set(false);
}
pub fn set_high(&mut self) {
self.set(true);
}
pub fn toggle(&mut self) {
if self.is_low() {
self.set_high();
} else {
self.set_low();
}
}
pub fn is_low(&mut self) -> bool {
!self.is_high()
}
pub fn is_high(&mut self) -> bool {
self.avr.sim().get_digital_pin(self.port, self.pin)
}
pub fn is_input(&mut self) -> bool {
!self.is_output()
}
pub fn is_output(&mut self) -> bool {
self.avr
.sim()
.get_digital_pin_mode(self.port, self.pin)
.is_output()
}
#[track_caller]
pub fn assert(&mut self, high: bool) {
if high {
self.assert_high();
} else {
self.assert_low();
}
}
#[track_caller]
pub fn assert_low(&mut self) {
assert!(self.is_low(), "{} is not low", self.name());
}
#[track_caller]
pub fn assert_high(&mut self) {
assert!(self.is_high(), "{} is not high", self.name());
}
#[track_caller]
pub fn assert_input(&mut self) {
assert!(
self.is_input(),
"{} is not configured as input",
self.name()
);
}
#[track_caller]
pub fn assert_output(&mut self) {
assert!(
self.is_output(),
"{} is not configured as output",
self.name()
);
}
pub fn pulse_in(&mut self) -> AvrDuration {
let mut tt = AvrDuration::zero(self.avr);
let state = self.is_high();
while self.is_high() == state {
tt += self.avr.run();
}
tt
}
pub fn wait_while_low(&mut self) -> AvrDuration {
let mut tt = AvrDuration::zero(self.avr);
while self.is_low() {
tt += self.avr.run();
}
tt
}
pub fn wait_while_low_timeout(
&mut self,
timeout: AvrDuration,
) -> Result<AvrDuration, AvrDuration> {
let mut tt = AvrDuration::zero(self.avr);
while self.is_low() {
if tt >= timeout {
return Err(tt);
}
tt += self.avr.run();
}
Ok(tt)
}
pub fn wait_while_high(&mut self) -> AvrDuration {
let mut tt = AvrDuration::zero(self.avr);
while self.is_high() {
tt += self.avr.run();
}
tt
}
pub fn wait_while_high_timeout(
&mut self,
timeout: AvrDuration,
) -> Result<AvrDuration, AvrDuration> {
let mut tt = AvrDuration::zero(self.avr);
while self.is_high() {
if tt >= timeout {
return Err(tt);
}
tt += self.avr.run();
}
Ok(tt)
}
pub fn name(&self) -> String {
format!("P{}{}", self.port, self.pin)
}
}
pub struct DigitalPinAsync {
port: char,
pin: u8,
}
impl DigitalPinAsync {
pub(crate) fn new(port: char, pin: u8) -> Self {
Self { port, pin }
}
pub fn set(&self, high: bool) {
ComponentRuntime::with(|rt| {
rt.sim().set_digital_pin(self.port, self.pin, high);
})
}
pub fn set_low(&self) {
self.set(false);
}
pub fn set_high(&self) {
self.set(true);
}
pub fn toggle(&self) {
if self.is_low() {
self.set_high();
} else {
self.set_low();
}
}
pub fn is_low(&self) -> bool {
!self.is_high()
}
pub fn is_high(&self) -> bool {
ComponentRuntime::with(|rt| {
rt.sim().get_digital_pin(self.port, self.pin)
})
}
pub fn is_input(&self) -> bool {
!self.is_output()
}
pub fn is_output(&self) -> bool {
ComponentRuntime::with(|rt| {
rt.sim()
.get_digital_pin_mode(self.port, self.pin)
.is_output()
})
}
#[track_caller]
pub fn assert_low(&self) {
assert!(self.is_low(), "{} is not low", self.name());
}
#[track_caller]
pub fn assert_high(&self) {
assert!(self.is_high(), "{} is not high", self.name());
}
#[track_caller]
pub fn assert_input(&mut self) {
assert!(
self.is_input(),
"{} is not configured as input",
self.name()
);
}
#[track_caller]
pub fn assert_output(&mut self) {
assert!(
self.is_output(),
"{} is not configured as output",
self.name()
);
}
pub async fn pulse_in(&self) -> AvrDuration {
let mut tt = ComponentRuntime::with(|rt| {
AvrDuration::new(rt.clock_frequency(), 0)
});
let state = self.is_high();
while self.is_high() == state {
tt += avr_rt().run().await;
}
tt
}
pub async fn wait_while_low(&self) -> AvrDuration {
let mut tt = ComponentRuntime::with(|rt| {
AvrDuration::new(rt.clock_frequency(), 0)
});
while self.is_low() {
tt += avr_rt().run().await;
}
tt
}
pub async fn wait_while_high(&self) -> AvrDuration {
let mut tt = ComponentRuntime::with(|rt| {
AvrDuration::new(rt.clock_frequency(), 0)
});
while self.is_high() {
tt += avr_rt().run().await;
}
tt
}
pub fn name(&self) -> String {
format!("P{}{}", self.port, self.pin)
}
}