// All devices are implemented here. use slog::Logger; pub mod oscillator; pub mod ram; pub mod usart; pub trait DeviceImpl { /// addr relative to the start of the device memory map. fn read(&mut self, addr: u32) -> u8; /// addr relative to the start of the device memory map. fn write(&mut self, addr: u32, value: u8); } pub struct Device { start_addr: u32, addr_len: u32, device: Box, } impl Device { pub fn new(device: Box, start_addr: u32, addr_len: u32) -> Self { Self { start_addr, addr_len, device, } } pub fn handles_addr(&self, addr: u32) -> bool { addr >= self.start_addr && addr - self.start_addr < self.addr_len } pub fn read(&mut self, addr: u32) -> u8 { self.device.read(addr - self.start_addr) } pub fn write(&mut self, addr: u32, val: u8) { self.device.write(addr - self.start_addr, val) } } pub struct DeviceTree { log: Logger, devices: Vec, } impl DeviceTree { pub fn new(log: Logger) -> Self { Self { log, devices: Vec::new(), } } pub fn add_device(&mut self, device: Device) { self.devices.push(device); } fn get_device_for_addr(&mut self, addr: u32) -> Option<&mut Device> { self.devices.iter_mut().find(|d| d.handles_addr(addr)) } pub fn read(&mut self, addr: u32) -> u8 { if let Some(ref mut d) = self.get_device_for_addr(addr) { return d.read(addr); } warn!(self.log, "Trying to read unmapped I/O: {:08X}", addr); 0 } pub fn write(&mut self, addr: u32, val: u8) { if let Some(ref mut d) = self.get_device_for_addr(addr) { return d.write(addr, val); } warn!( self.log, "Trying to write unmapped I/O: {:08X} <- {:02X}", addr, val ); } }