use crate::memregs::{read_u32_mapped, write_u32_mapped};
pub struct Register {
pub name: String,
pub offset: u32,
pub raw: u32,
pub children: Vec<SubRegister>,
}
#[derive(Clone)]
pub struct SubRegister {
pub name: String,
pub msb: u8,
pub lsb: u8,
}
impl Register {
pub fn new(name: &str, offset: u32, children: Vec<SubRegister>) -> Self {
Register {
name: name.to_string(),
offset,
raw: 0,
children,
}
}
pub(crate) fn read(&mut self, map_ptr: *mut u8, iface_offset: isize) -> Result<u32, String> {
let val = read_u32_mapped(map_ptr, iface_offset, self.offset);
self.raw = val;
Ok(val)
}
pub(crate) fn write(
&mut self,
map_ptr: *mut u8,
iface_offset: isize,
value: u32,
) -> Result<(), String> {
write_u32_mapped(map_ptr, iface_offset, self.offset, value);
self.raw = value;
Ok(())
}
pub(crate) fn get_subregister(&self, name: &str) -> Option<&SubRegister> {
self.children.iter().find(|sub| sub.name == name)
}
pub(crate) fn read_subregister(
&mut self,
sub: &SubRegister,
refresh: bool,
map_ptr: Option<*mut u8>,
iface_offset: isize,
) -> Result<u32, String> {
if refresh {
if let Some(ptr) = map_ptr {
self.read(ptr, iface_offset)?;
} else {
return Err("Mapped pointer not available".to_string());
}
}
let mask = sub.mask();
Ok((self.raw & mask) >> sub.lsb)
}
pub(crate) fn write_subregister(
&mut self,
sub: &SubRegister,
value: u32,
refresh: bool,
map_ptr: Option<*mut u8>,
iface_offset: isize,
) -> Result<(), String> {
if refresh {
if let Some(ptr) = map_ptr {
self.read(ptr, iface_offset)?;
} else {
return Err("Mapped pointer not available".to_string());
}
}
let mask = sub.mask();
self.raw = (self.raw & !mask) | ((value << sub.lsb) & mask);
if let Some(ptr) = map_ptr {
self.write(ptr, iface_offset, self.raw)?;
} else {
return Err("Mapped pointer not available".to_string());
}
Ok(())
}
}
impl SubRegister {
pub fn new(name: &str, msb: u8, lsb: u8) -> Self {
SubRegister {
name: name.to_string(),
msb,
lsb,
}
}
pub fn mask(&self) -> u32 {
if self.msb < self.lsb || self.msb > 31 {
0
} else {
((1u32 << (self.msb - self.lsb + 1)) - 1) << self.lsb
}
}
}