Skip to main content

avr_simulator/
lib.rs

1//! Oxidized interface for simavr.
2//!
3//! The main purpose of this crate is to serve as a building block for the
4//! `avr-tester` crate, providing a safe and curated access to simavr.
5//!
6//! See: [`AvrSimulator::new()`].
7
8mod adc;
9mod avr;
10mod duration;
11mod firmware;
12mod ioctl;
13mod logging;
14mod port;
15mod spi;
16mod state;
17mod twi;
18mod uart;
19
20use self::adc::*;
21use self::avr::*;
22pub use self::duration::*;
23use self::firmware::*;
24use self::ioctl::*;
25pub use self::port::PinMode;
26use self::port::*;
27use self::spi::*;
28pub use self::state::*;
29use self::twi::*;
30pub use self::twi::{TwiPacket, TwiSlave};
31use self::uart::*;
32pub use simavr_ffi as ffi;
33use std::collections::HashMap;
34use std::path::Path;
35
36#[derive(Debug)]
37pub struct AvrSimulator {
38    avr: Avr,
39    adc: Option<Adc>,
40    spis: HashMap<u8, Spi>,
41    twis: HashMap<u8, Twi>,
42    uarts: HashMap<char, Uart>,
43}
44
45impl AvrSimulator {
46    pub fn new(mcu: &str, frequency: u32, firmware: impl AsRef<Path>) -> Self {
47        logging::init();
48
49        let mut avr = Avr::new(mcu, frequency);
50
51        Firmware::new()
52            .load(firmware, None, Some(mcu), Some(frequency), None)
53            .flash_to(&mut avr);
54
55        // Safety: `avr` lives as long as `adc`, `spis` etc.
56        let adc = unsafe { Adc::new(&avr) };
57        let spis = unsafe { Self::init_spis(&avr) };
58        let twis = unsafe { Self::init_twis(&avr) };
59        let uarts = unsafe { Self::init_uarts(&mut avr) };
60
61        Self {
62            avr,
63            adc,
64            spis,
65            twis,
66            uarts,
67        }
68    }
69
70    unsafe fn init_spis(avr: &Avr) -> HashMap<u8, Spi> {
71        let mut spis = HashMap::new();
72
73        for id in 0..8 {
74            if let Some(spi) = unsafe { Spi::new(id, avr) } {
75                spis.insert(id, spi);
76            } else {
77                break;
78            }
79        }
80
81        spis
82    }
83
84    unsafe fn init_twis(avr: &Avr) -> HashMap<u8, Twi> {
85        let mut twis = HashMap::new();
86
87        for id in 0..8 {
88            if let Some(twi) = unsafe { Twi::new(id, avr) } {
89                twis.insert(id, twi);
90            } else {
91                break;
92            }
93        }
94
95        twis
96    }
97
98    unsafe fn init_uarts(avr: &mut Avr) -> HashMap<char, Uart> {
99        let mut uarts = HashMap::new();
100
101        for id in 0..8 {
102            let id = (b'0' + id) as char;
103
104            if let Some(uart) = unsafe { Uart::new(id, avr) } {
105                uarts.insert(id, uart);
106            } else {
107                break;
108            }
109        }
110
111        uarts
112    }
113
114    pub fn step(&mut self) -> StepOutcome {
115        for uart in self.uarts.values_mut() {
116            uart.flush();
117        }
118
119        let cycle = self.avr.cycle();
120        let state = self.avr.run();
121        let tt = (self.avr.cycle() - cycle).max(1);
122        let tt = AvrDuration::new(self.avr.frequency(), tt);
123
124        StepOutcome { state, tt }
125    }
126
127    pub fn read_spi(&mut self, id: u8) -> Option<u8> {
128        self.spi(id).read()
129    }
130
131    pub fn write_spi(&mut self, id: u8, byte: u8) {
132        self.spi(id).write(byte)
133    }
134
135    pub fn set_twi_slave(&mut self, id: u8, slave: impl TwiSlave + 'static) {
136        self.twi(id).set_slave(slave);
137    }
138
139    pub fn read_uart(&mut self, id: char) -> Option<u8> {
140        self.uart(id).read()
141    }
142
143    pub fn write_uart(&mut self, id: char, byte: u8) {
144        self.uart(id).write(byte)
145    }
146
147    pub fn get_digital_pin(&mut self, port: char, pin: u8) -> bool {
148        Pin::get(&mut self.avr, port, pin)
149    }
150
151    pub fn set_digital_pin(&mut self, port: char, pin: u8, high: bool) {
152        Pin::set(&self.avr, port, pin, high);
153    }
154
155    pub fn get_digital_pin_mode(&mut self, port: char, pin: u8) -> PinMode {
156        Pin::get_mode(&mut self.avr, port, pin)
157    }
158
159    pub fn set_analog_pin(&mut self, pin: u8, voltage: u32) {
160        self.adc
161            .as_mut()
162            .expect("Current AVR doesn't have ADC")
163            .set_voltage(pin, voltage);
164    }
165
166    fn spi(&mut self, id: u8) -> &mut Spi {
167        self.spis
168            .get_mut(&id)
169            .unwrap_or_else(|| panic!("Current AVR doesn't have SPI{}", id))
170    }
171
172    fn twi(&mut self, id: u8) -> &mut Twi {
173        self.twis
174            .get_mut(&id)
175            .unwrap_or_else(|| panic!("Current AVR doesn't have TWI{}", id))
176    }
177
178    fn uart(&mut self, id: char) -> &mut Uart {
179        self.uarts
180            .get_mut(&id)
181            .unwrap_or_else(|| panic!("Current AVR doesn't have UART{}", id))
182    }
183}
184
185#[derive(Clone, Copy, Debug, PartialEq, Eq)]
186pub struct StepOutcome {
187    /// AVR's state after the instruction
188    pub state: AvrState,
189
190    /// How long it took to execute the instruction, in AVR cycles; approximate;
191    /// always greater than zero
192    pub tt: AvrDuration,
193}