mod builder;
mod components;
mod duration_ext;
mod pins;
mod read;
mod spi;
mod twi;
mod uart;
mod utils;
mod write;
pub use self::builder::*;
pub use self::components::*;
pub use self::duration_ext::*;
pub use self::pins::*;
pub use self::read::*;
pub use self::spi::*;
pub use self::twi::*;
pub use self::uart::*;
pub use self::utils::*;
pub use self::write::*;
pub use avr_simulator::{AvrDuration, TwiPacket, TwiSlave};
use avr_simulator::{AvrSimulator, AvrState};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::marker::PhantomData;
use std::path::Path;
use std::rc::Rc;
type TwiId = u8;
pub struct AvrTester {
sim: Option<AvrSimulator>,
clock_frequency: u32,
remaining_clock_cycles: Option<u64>,
components: Components,
twis: BTreeMap<TwiId, Rc<RefCell<TwiManager>>>,
}
impl AvrTester {
pub(crate) fn new(
mcu: &str,
clock_frequency: u32,
firmware: impl AsRef<Path>,
remaining_clock_cycles: Option<u64>,
) -> Self {
Self {
sim: Some(AvrSimulator::new(mcu, clock_frequency, firmware)),
clock_frequency,
remaining_clock_cycles,
components: Components::new(),
twis: Default::default(),
}
}
#[doc(hidden)]
pub fn test() -> Self {
todo!();
}
pub fn run(&mut self) -> AvrDuration {
let step = self.sim().step();
self.components
.run(&mut self.sim, self.clock_frequency, step.tt);
if let Some(remaining_clock_cycles) = &mut self.remaining_clock_cycles {
*remaining_clock_cycles =
remaining_clock_cycles.saturating_sub(step.tt.as_cycles());
if *remaining_clock_cycles == 0 {
panic!("Test timed-out");
}
}
match step.state {
AvrState::Running => {
}
AvrState::Crashed => {
panic!(
"AVR crashed (e.g. the program stepped on an invalid \
instruction)"
);
}
AvrState::Sleeping => {
panic!(
"AVR went to sleep (this panics, because AvrTester doesn't \
provide any way to wake up the microcontroller yet)"
);
}
state => {
panic!("Unexpected AvrState: {:?}", state);
}
}
step.tt
}
pub fn run_for(&mut self, n: impl IntoCycles) {
let mut cycles = n.into_cycles();
while cycles > 0 {
cycles = cycles.saturating_sub(self.run().as_cycles());
}
}
pub fn run_for_us(&mut self, n: u64) {
self.run_for(AvrDuration::micros(self, n));
}
pub fn run_for_ms(&mut self, n: u64) {
self.run_for(AvrDuration::millis(self, n));
}
pub fn run_for_s(&mut self, n: u64) {
self.run_for(AvrDuration::secs(self, n));
}
pub fn pins(&mut self) -> Pins {
Pins::new(self)
}
#[doc(alias = "spi")]
pub fn spi0(&mut self) -> Spi {
Spi::new(self.sim(), 0)
}
pub fn spi1(&mut self) -> Spi {
Spi::new(self.sim(), 1)
}
#[doc(alias = "i2c")]
pub fn twi0(&mut self) -> Twi {
Twi::new(self, 0)
}
pub fn twi1(&mut self) -> Twi {
Twi::new(self, 1)
}
#[doc(alias = "uart")]
pub fn uart0(&mut self) -> Uart {
Uart::new(self.sim(), '0')
}
pub fn uart1(&mut self) -> Uart {
Uart::new(self.sim(), '1')
}
pub fn components(&mut self) -> &mut Components {
&mut self.components
}
fn sim(&mut self) -> &mut AvrSimulator {
self.sim.as_mut().expect(
"AvrSimulator had been deallocated - has some component crashed?",
)
}
}
pub struct AvrTesterAsync {
_pd: PhantomData<()>,
}
impl AvrTesterAsync {
fn new() -> Self {
Self {
_pd: Default::default(),
}
}
pub async fn run(&self) -> AvrDuration {
ResumeFuture::new().await
}
pub async fn run_for(&self, n: impl IntoCycles) {
let cycles = n.into_cycles();
let fut = ComponentRuntime::with(|rt| {
SleepFuture::new(AvrDuration::new(rt.clock_frequency(), cycles))
});
fut.await;
}
pub async fn run_for_us(&self, n: u64) {
let fut = ComponentRuntime::with(|rt| {
SleepFuture::new(
AvrDuration::new(rt.clock_frequency(), 0).with_micros(n),
)
});
fut.await;
}
pub async fn run_for_ms(&self, n: u64) {
let fut = ComponentRuntime::with(|rt| {
SleepFuture::new(
AvrDuration::new(rt.clock_frequency(), 0).with_millis(n),
)
});
fut.await;
}
pub async fn run_for_s(&self, n: u64) {
let fut = ComponentRuntime::with(|rt| {
SleepFuture::new(
AvrDuration::new(rt.clock_frequency(), 0).with_secs(n),
)
});
fut.await;
}
pub fn pins(&self) -> PinsAsync {
PinsAsync::new()
}
pub fn spi0(&self) -> SpiAsync {
SpiAsync::new(0)
}
pub fn spi1(&self) -> SpiAsync {
SpiAsync::new(1)
}
pub fn uart0(&mut self) -> UartAsync {
UartAsync::new('0')
}
pub fn uart1(&mut self) -> UartAsync {
UartAsync::new('1')
}
}
pub fn avr_rt() -> AvrTesterAsync {
AvrTesterAsync::new()
}
macro_rules! constructors {
( $( $name:ident ),* $(,)? ) => {
impl AvrTester {
$(
pub fn $name() -> AvrTesterBuilder {
AvrTesterBuilder::new(stringify!($name))
}
)*
}
}
}
constructors! {
atmega8, atmega81,
atmega16,
atmega16m1,
atmega32,
atmega32u4,
atmega48, atmega48p, atmega48pa,
atmega64m1,
atmega88, atmega88p, atmega88pa,
atmega128, atmega128l,
atmega128rfa1,
atmega128rfr2,
atmega164, atmega164p, atmega164pa,
atmega168, atmega168p, atmega168pa,
atmega169p,
atmega324, atmega324p,
atmega324a, atmega324pa,
atmega328, atmega328p,
atmega328pb,
atmega644, atmega644p,
atmega1280,
atmega1281,
atmega1284p, atmega1284,
atmega2560, atmega2561,
attiny13, attiny13a,
attiny24,
attiny25,
attiny44,
attiny45,
attiny84,
attiny85,
attiny2313, attiny2313v,
attiny2313a,
attiny4313,
}