use std::ops::{Bound, RangeBounds};
use rand::Rng;
use super::ExternalDevice;
#[derive(Clone, Copy)]
struct SampleRange {
start: u32,
end: u32,
end_incl: bool
}
impl SampleRange {
fn new(r: impl RangeBounds<u32>) -> Self {
let start = match r.start_bound() {
Bound::Included(&s) => s,
Bound::Excluded(&s) => s.checked_add(1).expect("(Bound::Excluded(u32::MAX), _) is not an acceptable range"),
Bound::Unbounded => 0,
};
let (end, end_incl) = match r.end_bound() {
Bound::Included(&s) => (s, true),
Bound::Excluded(&s) => (s, false),
Bound::Unbounded => (u32::MAX, true),
};
Self { start, end, end_incl }
}
}
impl std::fmt::Debug for SampleRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SampleRange { start, end, end_incl: true } => (start..=end).fmt(f),
SampleRange { start, end, end_incl: false } => (start..end).fmt(f),
}
}
}
impl RangeBounds<u32> for SampleRange {
fn start_bound(&self) -> Bound<&u32> {
Bound::Included(&self.start)
}
fn end_bound(&self) -> Bound<&u32> {
match self.end_incl {
true => Bound::Included(&self.end),
false => Bound::Excluded(&self.end),
}
}
}
#[derive(Debug)]
pub struct TimerDevice {
generator: Box<rand::rngs::StdRng>,
range: SampleRange,
time: u32,
pub vect: u8,
pub priority: u8,
pub enabled: bool,
}
impl TimerDevice {
pub fn new(seed: Option<u64>, range: impl RangeBounds<u32>, vect: u8, priority: u8) -> Self {
use rand::SeedableRng;
use rand::rngs::StdRng;
let generator = match seed {
Some(s) => StdRng::seed_from_u64(s),
None => StdRng::from_os_rng(),
};
let mut timer = Self {
generator: Box::new(generator),
range: SampleRange::new(range),
time: 0,
vect,
priority,
enabled: false
};
timer.reset_remaining();
timer
}
pub fn get_range(&self) -> impl RangeBounds<u32> {
self.range
}
pub fn set_range(&mut self, r: impl RangeBounds<u32>) -> &mut Self {
self.range = SampleRange::new(r);
self
}
pub fn set_exact(&mut self, n: u32) -> &mut Self {
self.set_range(n..=n)
}
pub fn get_remaining(&self) -> u32 {
self.time
}
pub fn reset_remaining(&mut self) {
self.time = self.try_generate_time();
}
fn try_generate_time(&mut self) -> u32 {
match self.range {
SampleRange { start, end, end_incl: true } => self.generator.random_range(start..=end),
SampleRange { start, end, end_incl: false } => self.generator.random_range(start..end),
}
}
}
impl Default for TimerDevice {
fn default() -> Self {
Self::new(None, 50..=50, 0x81, 0b100)
}
}
impl ExternalDevice for TimerDevice {
fn io_read(&mut self, _addr: u16, _effectful: bool) -> Option<u16> {
None
}
fn io_write(&mut self, _addr: u16, _data: u16) -> bool {
false
}
fn io_reset(&mut self) {
self.time = self.try_generate_time();
}
fn poll_interrupt(&mut self) -> Option<super::Interrupt> {
if !self.enabled { return None };
match self.time {
0 => {
self.reset_remaining();
None
},
1 => {
self.time = 0;
Some(super::Interrupt::vectored(self.vect, self.priority))
},
_ => {
self.time -= 1;
None
}
}
}
}